[TOOLS][HHPCOMP] Initial commit of hhpcomp, our new HTML Help Project (*.hhp) compiler

svn path=/trunk/; revision=68685
This commit is contained in:
Benedikt Freisen 2015-08-11 13:37:36 +00:00
parent 261083ff50
commit 65780ec3c1
22 changed files with 4956 additions and 0 deletions

View file

@ -15,6 +15,7 @@ add_executable(utf16le utf16le/utf16le.cpp)
add_subdirectory(cabman)
add_subdirectory(cdmake)
add_subdirectory(hhpcomp)
add_subdirectory(hpp)
add_subdirectory(kbdtool)
add_subdirectory(mkhive)

View file

@ -0,0 +1,15 @@
list(APPEND SOURCE
hhpcomp.cpp
hhp_reader.cpp
utils.cpp
chmc/chmc.c
chmc/err.c
lzx_compress/lz_nonslide.c
lzx_compress/lzx_layer.c)
# used by lzx_compress
add_definitions(-DNONSLIDE)
add_executable(hhpcomp ${SOURCE})
target_link_libraries(hhpcomp m)

View file

@ -0,0 +1,11 @@
LICENSING CLEARIFICATION
1. files unique to hhpcomp: LGPL version 2.1 or later
2. files borrowed from chmc: GPL version 3 or later
3. files borrowed from lzxcomp: LGPL version 2.1 only
whole project: GPL version 3 or later (via implicit relicensing of 1. and 3.)
copies of the respective license texts can be found in the top level directory
see http://sourceforge.net/projects/chmc for unmodified sources of 2. and 3.

View file

@ -0,0 +1,177 @@
/*
Copyright (C) 2010 Alex Andreotti <alex.andreotti@gmail.com>
This file is part of chmc.
chmc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
chmc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with chmc. If not, see <http://www.gnu.org/licenses/>.
NOTE this file is mainly based on chm_lib.c from chmLib by Jed Wing
http://www.jedrea.com/chmlib/
*/
#ifndef CHMC_CHM_H
#define CHMC_CHM_H
/*
* architecture specific defines
*
* Note: as soon as C99 is more widespread, the below defines should
* probably just use the C99 sized-int types.
*
* The following settings will probably work for many platforms. The sizes
* don't have to be exactly correct, but the types must accommodate at least as
* many bits as they specify.
*/
/* i386, 32-bit, Windows */
#ifdef WIN32
typedef unsigned char UChar;
typedef __int16 Int16;
typedef unsigned __int16 UInt16;
typedef __int32 Int32;
typedef unsigned __int32 UInt32;
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
/* I386, 32-bit, non-Windows */
/* Sparc */
/* MIPS */
/* PPC */
#elif __i386__ || __sun || __sgi || __ppc__
typedef unsigned char UChar;
typedef short Int16;
typedef unsigned short UInt16;
typedef long Int32;
typedef unsigned long UInt32;
typedef long long Int64;
typedef unsigned long long UInt64;
/* x86-64 */
/* Note that these may be appropriate for other 64-bit machines. */
#elif __x86_64__ || __ia64__
typedef unsigned char UChar;
typedef short Int16;
typedef unsigned short UInt16;
typedef int Int32;
typedef unsigned int UInt32;
typedef long Int64;
typedef unsigned long UInt64;
#else
/* yielding an error is preferable to yielding incorrect behavior */
#error "Please define the sized types for your platform"
#endif
/* GCC */
#ifdef __GNUC__
#define memcmp __builtin_memcmp
#define memset __builtin_memset
#define memcpy __builtin_memcpy
#define strlen __builtin_strlen
#endif
#define _CHMC_ITSF_V3_LEN (0x60)
struct chmcItsfHeader {
char signature[4]; /* 0 (ITSF) */
Int32 version; /* 4 */
Int32 header_len; /* 8 */
Int32 unknown_000c; /* c */
UInt32 last_modified; /* 10 */
UInt32 lang_id; /* 14 */
UChar dir_uuid[16]; /* 18 */
UChar stream_uuid[16]; /* 28 */
UInt64 sect0_offset; /* 38 */
UInt64 sect0_len; /* 40 */
UInt64 dir_offset; /* 48 */
UInt64 dir_len; /* 50 */
UInt64 data_offset; /* 58 (Not present before V3) */
}; /* __attribute__ ((aligned (1))); */
#define _CHMC_SECT0_LEN (0x18)
struct chmcSect0 {
Int32 unknown_0000; /* 0 */
Int32 unknown_0004; /* 4 */
UInt64 file_len; /* 8 */
Int32 unknown_0010; /* 10 */
Int32 unknown_0014; /* 14 */
};
#define CHM_IDX_INTVL 2
/* structure of ITSP headers */
#define _CHMC_ITSP_V1_LEN (0x54)
struct chmcItspHeader {
char signature[4]; /* 0 (ITSP) */
Int32 version; /* 4 */
Int32 header_len; /* 8 */
Int32 unknown_000c; /* c */
UInt32 block_len; /* 10 */
Int32 blockidx_intvl; /* 14 */
Int32 index_depth; /* 18 */
Int32 index_root; /* 1c */
Int32 index_head; /* 20 */
Int32 index_last; /* 24 */
Int32 unknown_0028; /* 28 */
UInt32 num_blocks; /* 2c */
UInt32 lang_id; /* 30 */
UChar system_uuid[16]; /* 34 */
UInt32 header_len2; /* 44 */
UChar unknown_0048[12]; /* 48 */
}; /* __attribute__ ((aligned (1))); */
/* structure of PMGL headers */
#define _CHMC_PMGL_LEN (0x14)
struct chmcPmglHeader
{
char signature[4]; /* 0 (PMGL) */
UInt32 free_space; /* 4 */
UInt32 unknown_0008; /* 8 */
Int32 block_prev; /* c */
Int32 block_next; /* 10 */
}; /* __attribute__ ((aligned (1))); */
#define _CHMC_PMGI_LEN (0x08)
struct chmcPmgiHeader {
char signature[4]; /* 0 (PMGI) */
UInt32 free_space; /* 4 */
}; /* __attribute__ ((aligned (1))); */
/* structure of LZXC reset table */
#define _CHMC_LZXC_RESETTABLE_V1_LEN (0x28)
struct chmcLzxcResetTable {
UInt32 version;
UInt32 block_count;
UInt32 entry_size;
UInt32 table_offset;
UInt64 uncompressed_len;
UInt64 compressed_len;
UInt64 block_len;
}; /* __attribute__ ((aligned (1))); */
/* structure of LZXC control data block */
#define _CHMC_LZXC_MIN_LEN (0x18)
#define _CHMC_LZXC_V2_LEN (0x1c)
struct chmcLzxcControlData {
UInt32 size; /* 0 */
char signature[4]; /* 4 (LZXC) */
UInt32 version; /* 8 */
UInt32 resetInterval; /* c */
UInt32 windowSize; /* 10 */
UInt32 windowsPerReset; /* 14 */
UInt32 unknown_18; /* 18 */
};
#endif /* CHMC_CHM_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,261 @@
/*
Copyright (C) 2010 Alex Andreotti <alex.andreotti@gmail.com>
This file is part of chmc.
chmc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
chmc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with chmc. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CHMC_CHMC_H
#define CHMC_CHMC_H
#include <stdlib.h>
#include <limits.h>
#include "chm.h"
#include "list.h"
#define CHMC_DIR_UUID \
"\x10\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\x00\xa0\xc9\x22\xe6\xec"
#define CHMC_STREAM_UUID \
"\x11\xfd\x01\x7c\xaa\x7b\xd0\x11\x9e\x0c\x00\xa0\xc9\x22\xe6\xec"
#define CHMC_SYSTEM_UUID \
"\x6a\x92\x02\x5d\x2e\x21\xd0\x11\x9d\xf9\x00\xa0\xc9\x22\xe6\xec"
struct chmcIndexHeader {
char signature[4];
Int32 unknown_4;
Int32 unknown_8;
Int32 num_of_topic;
Int32 unknown_10;
Int32 off_img_list;
Int32 unknown_18;
Int32 img_type_folder;
Int32 background;
Int32 foreground;
Int32 off_font;
Int32 win_style;
Int32 ex_win_style;
Int32 unknown_34;
Int32 off_frame_name;
Int32 off_win_name;
Int32 num_of_info;
Int32 unknown_44;
Int32 num_of_merge_files;
Int32 unknown_4c;
Int32 merge_files_offs[1004];
};
/* Sys Info Entry codes */
#define SIEC_DEFTOPIC 2
#define SIEC_TITLE 3
#define SIEC_LCASEFILE 6
#define SIEC_DEFWINDOW 5
/* present in files with Binary Index turned on. (eg: af 08 63 ac)
The entry in the #URLTBL file that points to the sitemap index had
the same first DWORD */
#define SIEC_HAVE_BINDX 7
#define SIEC_NUMOFINFOT 12
/* The #IDXHDR file contains exactly the same bytes (len 4096) */
#define SIEC_IDXHDR 13
#define SIEC_INFOCHKSUM 15
#define SIEC_DEFFONT 16
#define SIEC_TIMESTAMP 10
#define SIEC_COMPVER 9
#define SIEC_SYSINFO 4
/* NOTE use only as pointer */
#define _CHMC_SYS_ENTRY_HDR_LEN (sizeof(UInt16)*2)
struct chmcSystemEntry {
UInt16 code; /* FIXME check unsigned */
UInt16 len; /* FIXME check unsigned */
UChar data[65535];
};
/* NOTE use only as pointer */
#define _CHMC_SYS_ENTRY_NODE_HDR_LEN \
(sizeof(struct chmcSystemEntryNode *)+_CHMC_SYS_ENTRY_HDR_LEN)
struct chmcSystemEntryNode {
struct chmcSystemEntryNode *next;
struct chmcSystemEntry entry;
};
/* HHA Version 4.72.7294 and earlier */
#define _CHMC_SYS_INFO_V4_72_7294_LEN (28)
/* HHA Version 4.72.8086 and later */
#define _CHMC_SYS_INFO_V4_72_8086_LEN (36)
struct chmcSystemInfo {
UInt32 lcid;
UInt32 dbcs;
UInt32 full_search;
UInt32 klinks;
UInt32 alinks;
UInt64 timestamp;
UInt32 unknown_1c; // >= 8086 only
UInt32 unknown_20; // >= 8086 only
};
/* /usr/include/freetype2/freetype/ttnameid.h maybe useful */
#define CHMC_MS_LCID_EN_US (0x0409)
#define _CHMC_SYSTEM_HDR_LEN (sizeof(Int32)+sizeof(struct chmcSystemInfo))
struct chmcSystem {
Int32 version;
struct chmcSystemInfo info;
/* private: */
struct chmcSystemEntryNode *_entries;
UInt32 _size; /* keep track for alloc before save */
};
#define _CHMC_CHUNK_LEN (4096)
#define CHMC_PMGL_DATA_LEN (_CHMC_CHUNK_LEN - _CHMC_PMGL_LEN - 2)
struct chmcPmglChunk {
struct chmcPmglHeader header;
UChar data[CHMC_PMGL_DATA_LEN];
UInt16 entries_count;
};
struct chmcPmglChunkNode {
struct list_head list;
int data_len;
int index_len;
struct chmcPmglChunk chunk;
};
#define CHMC_PMGI_DATA_LEN (_CHMC_CHUNK_LEN - _CHMC_PMGI_LEN - 2)
struct chmcPmgiChunk {
struct chmcPmgiHeader header;
UChar data[CHMC_PMGI_DATA_LEN];
UInt16 entries_count;
};
struct chmcPmgiChunkNode {
struct list_head list;
int data_len;
int index_len;
struct chmcPmgiChunk chunk;
};
#define CHMC_TNFL_STATIC (1 << 0) /* don't free() */
struct chmcTreeNode {
struct list_head list;
UInt32 flags;
UInt32 sect_id;
char *name;
UInt16 prefixlen;
UChar *buf;
UInt64 offset;
UInt64 len;
};
struct chmcStringChunk {
struct list_head list;
UInt16 used;
UChar data[4096];
};
struct chmcConfig {
const char *title;
const char *tmpdir;
const char *hhc;
const char *hhk;
const char *deftopic;
UInt16 language;
};
struct chmcFile {
int fd;
struct chmcItsfHeader itsf;
struct chmcSect0 sect0;
struct chmcItspHeader itsp;
int sections_num;
struct list_head sections_list;
struct chmcSection **sections;
struct list_head pmgl_list;
struct chmcPmglChunkNode *pmgl_last;
struct list_head entries_list;
int entries_num;
struct chmcTreeNode **sort_entries;
struct list_head pmgi_list;
struct chmcPmgiChunkNode *pmgi_last;
struct chmcSystem system;
struct chmcIndexHeader idxhdr;
UChar *strings;
UInt32 strings_offset;
UInt32 strings_len;
struct chmcConfig *config;
};
#define CHMC_SECTNAME_MAXLEN (64)
struct chmcSection {
struct list_head list;
char name[CHMC_SECTNAME_MAXLEN];
UInt64 offset;
UInt64 len;
char filename[PATH_MAX];
int fd;
struct chmcLzxcResetTable reset_table_header;
struct chmcLzxcControlData control_data;
struct list_head mark_list;
int mark_count;
};
#define _CHMC_RSTTBL_MARK (sizeof(struct chmcResetTableMark))
struct chmcResetTableMark {
UInt64 at;
struct list_head list;
};
struct chmcUrlStrEntry {
UInt32 url_offset;
UInt32 framename_offset;
};
struct chmcUtlTblEntry {
UInt32 unknown;
UInt32 topic_index;
UInt32 urlstr_offset;
};
struct chmcTopicEntry {
UInt32 tocidx_offset;
UInt32 strings_offset;
UInt32 urltbl_offset;
short in_content;
short unknown;
};
int chmc_init(struct chmcFile *chm, const char *filename,
struct chmcConfig *config);
void chmc_sections_done(struct chmcFile *chm);
void chmc_term(struct chmcFile *chm);
int chmc_tree_done(struct chmcFile *chm);
#define chmc_dump(fmt, args...) fprintf(stderr, fmt , ##args)
#endif /* CHMC_CHMC_H */

View file

@ -0,0 +1,96 @@
/*
Copyright (C) 2010 Alex Andreotti <alex.andreotti@gmail.com>
This file is part of chmc.
chmc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
chmc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with chmc. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CHMC_ENCINT_H
#define CHMC_ENCINT_H
// 0x7f 127
// 0x3fff 16383
// 0x1fffff 2097151
// 0xfffffff 268435455
static inline int chmc_encint_len ( const UInt32 val ) {
int len;
// FIXME should support 64 bit?
if ( val > 0xfffffffUL )
len = 0; // overflow
else if ( val > 0x1fffffUL )
len = 4;
else if ( val > 0x3fffUL )
len = 3;
else if ( val > 0x7fUL )
len = 2;
else
len = 1;
return len;
}
static inline int chmc_encint ( const UInt32 val, UChar *out ) {
int len;
UInt32 a;
UChar *p, *l;
// FIXME should support 64 bit?
if ( ! out || val > 0xfffffffUL )
return 0; // FIXME can't handle, overflow
if ( val > 0x1fffffUL )
len = 4;
else if ( val > 0x3fffUL )
len = 3;
else if ( val > 0x7fUL )
len = 2;
else
len = 1;
a = val;
l = p = out + (len - 1);
while ( p >= out ) {
*p = (a & 0x7fUL);
if ( p < l )
*p |= 0x80UL;
p--;
a >>= 7;
}
return len;
}
static inline int chmc_decint ( const UChar *in, UInt32 *value ) {
int len;
len = 0;
*value = 0;
while ( (in[len] & 0x80) && (len < 3) ) {
*value <<= 7;
*value |= in[len] & 0x7f;
len++;
}
*value <<= 7;
*value |= in[len] & 0x7f;
len++;
return len;
}
#endif /* CHMC_ENCINT_H */

View file

@ -0,0 +1,66 @@
/*
Copyright (C) 2010 Alex Andreotti <alex.andreotti@gmail.com>
This file is part of chmc.
chmc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
chmc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with chmc. If not, see <http://www.gnu.org/licenses/>.
*/
#include "err.h"
#include <stdarg.h>
#include <assert.h>
struct chmcErr
{
int code;
char msg[CHMC_ERRMAXLEN+1];
};
static struct chmcErr chmc_err = {
.code = CHMC_NOERR,
.msg[0] = '\0',
};
void chmcerr_clean(void) {
chmc_err.code = CHMC_NOERR;
chmc_err.msg[0] = '\0';
}
int chmcerr_code(void) {
return chmc_err.code;
}
const char *chmcerr_message( void ) {
return chmc_err.msg;
}
void chmcerr_set(int code, const char *fmt, ...)
{
int len;
va_list ap;
chmc_err.code = code;
va_start(ap, fmt);
len = vsnprintf(chmc_err.msg, CHMC_ERRMAXLEN, fmt, ap);
if (len == CHMC_ERRMAXLEN)
chmc_err.msg[CHMC_ERRMAXLEN] = '\0';
assert(len <= CHMC_ERRMAXLEN);
va_end(ap);
}

View file

@ -0,0 +1,73 @@
/*
Copyright (C) 2010 Alex Andreotti <alex.andreotti@gmail.com>
This file is part of chmc.
chmc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
chmc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with chmc. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CHMC_ERR_H
#define CHMC_ERR_H
#include <stdio.h>
#define chmcerr_printf(fmt,args...) fprintf (stderr, fmt , ##args)
#include <stdlib.h>
#define BUG_ON(fmt, args...) \
do { \
fprintf (stderr, "%s:%d: ", __FILE__, __LINE__); \
fprintf (stderr, fmt , ##args); \
abort (); \
} while (0)
#define CHMC_ERRMAXLEN (1023)
#include <errno.h>
#define CHMC_NOERR (0)
#define CHMC_ENOMEM (ENOMEM)
#define CHMC_EINVAL (EINVAL)
void chmcerr_set(int code, const char *fmt, ...);
void chmcerr_clean(void);
int chmcerr_code(void);
const char *chmcerr_message(void);
#define chmc_error(fmt, args...) fprintf (stdout, fmt , ##args)
#define chmcerr_return_msg(fmt,args...) \
do { \
chmcerr_printf ( "%s: %d: ", __FILE__, __LINE__ ); \
chmcerr_printf ( "error %d: ", chmcerr_code () ); \
chmcerr_printf ( fmt , ##args ); \
chmcerr_printf ( ": %s\n", chmcerr_message () ); \
return chmcerr_code (); \
} while (0)
#define chmcerr_msg(fmt,args...) \
do { \
chmcerr_printf ("%s: %d: ", __FILE__, __LINE__); \
chmcerr_printf ("error %d: ", chmcerr_code ()); \
chmcerr_printf (fmt , ##args ); \
chmcerr_printf (": %s\n", chmcerr_message ()); \
} while (0)
#define chmcerr_set_return(code,fmt,args...) \
do { \
chmcerr_set ( (code), (fmt), ##args ); \
return (code); \
} while (0)
#endif /* CHMC_ERR_H */

View file

@ -0,0 +1,244 @@
#ifndef __LIST_H
#define __LIST_H
/* This file is from Linux Kernel (include/linux/list.h)
* and modified by simply removing hardware prefetching of list items.
* Here by copyright, credits attributed to wherever they belong.
* Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
*/
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *New,
struct list_head *prev,
struct list_head *next)
{
next->prev = New;
New->next = next;
New->prev = prev;
prev->next = New;
}
/**
* list_add - add a new entry
* @New: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *New, struct list_head *head)
{
__list_add(New, head, head->next);
}
/**
* list_add_tail - add a new entry
* @New: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *New, struct list_head *head)
{
__list_add(New, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (struct list_head *) 0;
entry->prev = (struct list_head *) 0;
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(struct list_head *head)
{
return head->next == head;
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
#endif

View file

@ -0,0 +1,262 @@
// This file is part of hhpcomp, a free HTML Help Project (*.hhp) compiler.
// Copyright (C) 2015 Benedikt Freisen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <stdlib.h>
#include "hhp_reader.h"
#include "utils.h"
using namespace std;
string hhp_section::get_name()
{
return name;
}
void hhp_section::set_name(string name)
{
this->name = name;
}
hhp_pair::hhp_pair(string key, bool has_default_value, string default_value)
{
this->key = key;
this->has_default_value = has_default_value;
this->default_value = default_value;
value_has_been_set = false;
}
void hhp_pair::set_value(string value)
{
this->value = value;
value_has_been_set = true;
}
string hhp_pair::get_value()
{
if (value_has_been_set)
return value;
else
{
if (has_default_value)
return default_value;
else
throw domain_error("pair '" + key + "' does not have a default value");
}
}
string hhp_pair::get_key()
{
return key;
}
void hhp_key_value_section::process_line(string line)
{
int pos_equals_sign = line.find_first_of('=');
if (pos_equals_sign == string::npos)
throw runtime_error("key-value pair does not contain an equals sign");
string key = to_upper(line.substr(0, pos_equals_sign));
string value = line.substr(pos_equals_sign + 1);
if (key.length() == 0)
throw runtime_error("key has length zero");
entries.find(key)->second->set_value(value);
}
void hhp_key_value_section::add_entry(hhp_pair* entry)
{
string upper_case_key = to_upper(entry->get_key());
if (entries.count(upper_case_key) != 0)
throw logic_error("trying to redundantly add key '" + upper_case_key + "'");
entries.insert(pair<string, hhp_pair*>(upper_case_key, entry));
}
hhp_options_section::hhp_options_section()
{
set_name("OPTIONS");
add_entry(binary_TOC = new hhp_pair("Binary TOC", true, "No"));
add_entry(binary_index = new hhp_pair("Binary Index", true, "Yes"));
add_entry(compiled_file = new hhp_pair("Compiled File", false));
add_entry(contents_file = new hhp_pair("Contents File", true, ""));
add_entry(index_file = new hhp_pair("Index File", true, ""));
add_entry(autoindex = new hhp_pair("AutoIndex", true, "No"));
add_entry(defaultwindow = new hhp_pair("DefaultWindow", true, ""));//?
add_entry(default_topic = new hhp_pair("Default Topic", true, "Index.htm"));//?
add_entry(defaultfont = new hhp_pair("DefaultFont", true, ""));
add_entry(language = new hhp_pair("Language", true, "0x409 English (US)"));//?
add_entry(title = new hhp_pair("Title", true, ""));//?
add_entry(createchifile = new hhp_pair("CreateCHIFile", true, "No"));
add_entry(compatibility = new hhp_pair("Compatibility", true, "1.1"));
add_entry(errorlogfile = new hhp_pair("ErrorLogFile", true, "Compiler.log"));//?
add_entry(full_text_search = new hhp_pair("Full-text search", true, "Yes"));//?
add_entry(display_compile_progress = new hhp_pair("Display compile progress", true, "Yes"));//?
add_entry(display_compile_note = new hhp_pair("Display compile note", true, "Yes"));//?
add_entry(flat = new hhp_pair("Flat", true, "No"));
add_entry(full_text_search_stop_list_file = new hhp_pair("Full text search stop list file", true, ""));
}
hhp_options_section::~hhp_options_section()
{
delete binary_TOC;
delete binary_index;
delete compiled_file;
delete contents_file;
delete index_file;
delete autoindex;
delete defaultwindow;
delete default_topic;
delete defaultfont;
delete language;
delete title;
delete createchifile;
delete compatibility;
delete errorlogfile;
delete full_text_search;
delete display_compile_progress;
delete display_compile_note;
delete flat;
delete full_text_search_stop_list_file;
}
hhp_files_section::hhp_files_section()
{
set_name("FILES");
}
void hhp_files_section::process_line(string line)
{
filenames.push_back(line);
}
hhp_reader::hhp_reader(string filename)
{
this->filename = filename;
options = new hhp_options_section();
add_section(options);
files = new hhp_files_section();
add_section(files);
read();
compute_unique_file_pathes_set();
}
hhp_reader::~hhp_reader()
{
delete options;
delete files;
}
void hhp_reader::add_section(hhp_section* section)
{
string upper_case_name = to_upper(section->get_name());
if (sections.count(upper_case_name) != 0)
throw logic_error("trying to redundantly add section '" + upper_case_name + "'");
sections.insert(pair<string, hhp_section*>(upper_case_name, section));
}
void hhp_reader::read()
{
ifstream hhp_file;
hhp_file.open(filename.c_str());
string line;
int line_number = 0;
hhp_section* section = NULL;
while (hhp_file.good())
{
getline(hhp_file, line);
line_number++;
if (line[line.length() - 1] == '\015') // delete CR character if present
line = line.substr(0, line.length() - 1);
if (line[0] == '[' && line[line.length() - 1] == ']')
{
string name = to_upper(line.substr(1, line.length() - 2));
if (sections.count(name))
{
section = sections.find(name)->second;
clog << section->get_name() << endl;
}
else
{
clog << "unknown section: " << name << endl;
}
}
else if (line[0] != ';' && !line.empty())
{
if (section)
section->process_line(line);
}
}
hhp_file.close();
}
void hhp_reader::compute_unique_file_pathes_set()
{
for (list<string>::iterator it = files->filenames.begin(); it != files->filenames.end(); ++it)
{
unique_file_pathes.insert(replace_backslashes(realpath(it->c_str())));
}
}
string hhp_reader::get_title_string()
{
return options->title->get_value();
}
string hhp_reader::get_contents_file_string()
{
return options->contents_file->get_value();
}
string hhp_reader::get_index_file_string()
{
return options->index_file->get_value();
}
string hhp_reader::get_default_topic_string()
{
return options->default_topic->get_value();
}
unsigned int hhp_reader::get_language_code()
{
return strtoul(options->language->get_value().c_str(), NULL, 0);
}
string hhp_reader::get_compiled_file_string()
{
return options->compiled_file->get_value();
}
set<string>::iterator hhp_reader::get_file_pathes_iterator_begin()
{
return unique_file_pathes.begin();
}
set<string>::iterator hhp_reader::get_file_pathes_iterator_end()
{
return unique_file_pathes.end();
}

View file

@ -0,0 +1,136 @@
// This file is part of hhpcomp, a free HTML Help Project (*.hhp) compiler.
// Copyright (C) 2015 Benedikt Freisen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <string>
#include <map>
#include <list>
#include <set>
using namespace std; // using 'using' here for convenience
class hhp_reader; // forward declaration
class hhp_section
{
private:
string name;
public:
virtual void process_line(string line) = 0;
string get_name();
void set_name(string name);
};
class hhp_pair
{
private:
string key;
bool value_has_been_set;
string value;
bool has_default_value;
string default_value;
public:
hhp_pair(string key, bool has_default_value = false, string default_value = "");
void set_value(string value);
string get_value();
string get_key();
};
class hhp_key_value_section : public hhp_section
{
protected:
map<string, hhp_pair*> entries;
void add_entry(hhp_pair* entry);
public:
virtual void process_line(string line);
};
class hhp_options_section : public hhp_key_value_section
{
friend hhp_reader;
private:
hhp_pair* binary_TOC;
hhp_pair* binary_index;
hhp_pair* compiled_file;
hhp_pair* contents_file;
hhp_pair* index_file;
hhp_pair* autoindex;
hhp_pair* defaultwindow;
hhp_pair* default_topic;
hhp_pair* defaultfont;
hhp_pair* language;
hhp_pair* title;
hhp_pair* createchifile;
hhp_pair* compatibility;
hhp_pair* errorlogfile;
hhp_pair* full_text_search;
hhp_pair* display_compile_progress;
hhp_pair* display_compile_note;
hhp_pair* flat;
hhp_pair* full_text_search_stop_list_file;
public:
hhp_options_section();
~hhp_options_section();
};
class hhp_files_section : public hhp_section
{
friend hhp_reader;
private:
list<string> filenames;
public:
hhp_files_section();
virtual void process_line(string line);
};
class hhp_reader
{
private:
string filename;
map<string, hhp_section*> sections;
hhp_options_section* options;
hhp_files_section* files;
set<string> unique_file_pathes;
void add_section(hhp_section* section);
void read();
void compute_unique_file_pathes_set();
public:
hhp_reader(string filename);
~hhp_reader();
string get_title_string();
string get_contents_file_string();
string get_index_file_string();
string get_default_topic_string();
unsigned int get_language_code();
string get_compiled_file_string();
set<string>::iterator get_file_pathes_iterator_begin();
set<string>::iterator get_file_pathes_iterator_end();
};

View file

@ -0,0 +1,90 @@
// This file is part of hhpcomp, a free HTML Help Project (*.hhp) compiler.
// Copyright (C) 2015 Benedikt Freisen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <iostream>
#include <string>
#include <set>
#include <stdexcept>
#include <sys/stat.h>
#include <unistd.h>
#include "hhp_reader.h"
#include "utils.h"
extern "C" {
#include "chmc/chmc.h"
#include "chmc/err.h"
}
extern "C" struct chmcTreeNode *chmc_add_file(struct chmcFile *chm, const char *filename,
UInt16 prefixlen, int sect_id, UChar *buf,
UInt64 len);
using namespace std;
int main(int argc, char** argv)
{
if (argc != 2)
{
cerr << "Usage: hhpcomp <input.hhp>" << endl;
exit(0);
}
string absolute_name = replace_backslashes(realpath(argv[1]));
int prefixlen = absolute_name.find_last_of('/');
clog << prefixlen << endl;
chdir(absolute_name.substr(0, prefixlen).c_str()); // change to the project file's directory
hhp_reader project_file(absolute_name);
struct chmcFile chm;
struct chmcConfig chm_config;
chm_config.title = project_file.get_title_string().c_str();
chm_config.hhc = project_file.get_contents_file_string().c_str();
chm_config.hhk = project_file.get_index_file_string().c_str();
chm_config.deftopic = project_file.get_default_topic_string().c_str();
chm_config.language = project_file.get_language_code();
int err;
err = chmc_init(&chm, replace_backslashes(project_file.get_compiled_file_string()).c_str(), &chm_config);
if (err)
{
cerr << "could not initialize chmc" << endl;
exit(EXIT_FAILURE);
}
for (set<string>::iterator it = project_file.get_file_pathes_iterator_begin();
it != project_file.get_file_pathes_iterator_end(); ++it)
{
clog << "File: " << *it << endl;
struct stat buf;
stat(it->c_str(), &buf);
if ((chmc_add_file(&chm, it->c_str(), prefixlen, 1, NULL, buf.st_size)) ? chmcerr_code() : CHMC_NOERR)
{
cerr << "could not add file: " << *it << endl;
exit(EXIT_FAILURE);
}
}
chmc_tree_done(&chm);
chmc_term(&chm);
}

View file

@ -0,0 +1,3 @@
2002-06-17 Matthew T. Russotto <mrussotto@speakeasy.net>
Switched to non-sliding version of Lempel-Ziv for
major performance boost

View file

@ -0,0 +1,388 @@
/*
File lz_nonslide.c, part of lzxcomp library
Copyright (C) 2002 Matthew T. Russotto
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; version 2.1 only
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Document here
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <strings.h>
#ifdef DEBUG_PERF
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "lz_nonslide.h"
#define MAX_MATCH 253
#define MIN_MATCH 2
void lz_init(lz_info *lzi, int wsize, int max_dist,
int max_match, int min_match,
int frame_size,
get_chars_t get_chars,
output_match_t output_match,
output_literal_t output_literal, void *user_data)
{
/* the reason for the separate max_dist value is LZX can't reach the
first three characters in its nominal window. But using a smaller
window results in inefficiency when dealing with reset intervals
which are the length of the nominal window */
lzi->wsize = wsize;
if (max_match > wsize)
lzi->max_match = wsize;
else
lzi->max_match = max_match;
lzi->min_match = min_match;
if (lzi->min_match < 3) lzi->min_match = 3;
lzi->max_dist = max_dist;
lzi->block_buf_size = wsize + lzi->max_dist;
lzi->block_buf = malloc(lzi->block_buf_size);
lzi->block_bufe = lzi->block_buf + lzi->block_buf_size;
assert(lzi->block_buf != NULL);
lzi->cur_loc = 0;
lzi->block_loc = 0;
lzi->chars_in_buf = 0;
lzi->eofcount = 0;
lzi->get_chars = get_chars;
lzi->output_match = output_match;
lzi->output_literal = output_literal;
lzi->user_data = user_data;
lzi->frame_size = frame_size;
lzi->lentab = calloc(sizeof(int), lzi->block_buf_size);
lzi->prevtab = calloc(sizeof(u_char *), lzi->block_buf_size);
lzi->analysis_valid = 0;
}
void lz_release(lz_info *lzi)
{
free(lzi->block_buf);
free(lzi->lentab);
free(lzi->prevtab);
}
void lz_reset(lz_info *lzi)
{
int residual = lzi->chars_in_buf - lzi->block_loc;
memmove(lzi->block_buf, lzi->block_buf + lzi->block_loc, residual);
lzi->chars_in_buf = residual;
lzi->block_loc = 0;
lzi->analysis_valid = 0;
}
#ifdef LZNONSLIDE_MAIN
typedef struct lz_user_data
{
FILE *infile;
FILE *outfile;
int R0, R1, R2;
} lz_user_data;
int tmp_get_chars(lz_info *lzi, int n, u_char *buf)
{
lz_user_data *lzud = (lz_user_data *)lzi->user_data;
return fread(buf, 1, n, lzud->infile);
}
int tmp_output_match(lz_info *lzi, int match_pos, int match_len)
{
lz_user_data *lzud = (lz_user_data *)lzi->user_data;
int mod_match_loc;
mod_match_loc = match_pos;
fprintf(lzud->outfile, "(%d, %d)(%d)\n", match_pos, match_len, mod_match_loc);
return 0;
}
void tmp_output_literal(lz_info *lzi, u_char ch)
{
lz_user_data *lzud = (lz_user_data *)lzi->user_data;
fprintf(lzud->outfile, "'%c'", ch);
}
int main(int argc, char *argv[])
{
int wsize = atoi(argv[1]);
lz_info lzi;
lz_user_data lzu = {stdin, stdout, 1, 1, 1};
lz_init(&lzi, wsize, wsize, MAX_MATCH, MIN_MATCH, 8192, tmp_get_chars, tmp_output_match, tmp_output_literal,&lzu);
lz_compress(&lzi);
return 0;
}
#endif
__inline__ int lz_left_to_process(lz_info *lzi)
{
return lzi->chars_in_buf - lzi->block_loc;
}
static void
fill_blockbuf(lz_info *lzi, int maxchars)
{
int toread;
u_char *readhere;
int nread;
if (lzi->eofcount) return;
maxchars -= lz_left_to_process(lzi);
toread = lzi->block_buf_size - lzi->chars_in_buf;
if (toread > maxchars) toread = maxchars;
readhere = lzi->block_buf + lzi->chars_in_buf;
nread = lzi->get_chars(lzi, toread, readhere);
lzi->chars_in_buf += nread;
if (nread != toread)
lzi->eofcount++;
}
static void lz_analyze_block(lz_info *lzi)
{
int *lentab, *lenp;
u_char **prevtab, **prevp;
u_char *bbp, *bbe;
u_char *chartab[256];
u_char *cursor;
int prevlen;
int ch;
int maxlen;
long wasinc;
int max_dist = lzi->max_dist;
#ifdef DEBUG_ANALYZE_BLOCK
static short n = 0;
#endif
#ifdef DEBUG_PERF
struct rusage innerloop;
struct timeval innertime, tmptime;
struct rusage outerloop;
struct timeval outertime;
struct rusage initialloop;
struct timeval initialtime;
struct rusage totalloop;
struct timeval totaltime;
#endif
#ifdef DEBUG_ANALYZE_BLOCK
fprintf(stderr, "Analyzing block %d, cur_loc = %06x\n", n, lzi->cur_loc);
#endif
memset(chartab, 0, sizeof(chartab));
prevtab = prevp = lzi->prevtab;
lentab = lenp = lzi->lentab;
memset(prevtab, 0, sizeof(*prevtab) * lzi->chars_in_buf);
memset(lentab, 0, sizeof(*prevtab) * lzi->chars_in_buf);
#ifdef DEBUG_PERF
memset(&innertime, 0, sizeof(innertime));
memset(&outertime, 0, sizeof(outertime));
getrusage(RUSAGE_SELF, &initialloop);
totalloop = initialloop;
#endif
bbp = lzi->block_buf;
bbe = bbp + lzi->chars_in_buf;
while (bbp < bbe) {
if (chartab[ch = *bbp]) {
*prevp = chartab[ch];
*lenp = 1;
}
chartab[ch] = bbp;
bbp++;
prevp++;
lenp++;
}
#ifdef DEBUG_PERF
initialtime = initialloop.ru_utime;
getrusage(RUSAGE_SELF, &initialloop);
timersub(&initialloop.ru_utime, &initialtime, &initialtime);
#endif
wasinc = 1;
for (maxlen = 1; wasinc && (maxlen < lzi->max_match); maxlen++) {
#ifdef DEBUG_PERF
getrusage(RUSAGE_SELF, &outerloop);
#endif
bbp = bbe - maxlen - 1;
lenp = lentab + lzi->chars_in_buf - maxlen - 1;
prevp = prevtab + lzi->chars_in_buf - maxlen - 1;
wasinc = 0;
while (bbp > lzi->block_buf) {
if (*lenp == maxlen) {
#ifdef DEBUG_PERF
getrusage(RUSAGE_SELF, &innerloop);
#endif
ch = bbp[maxlen];
cursor = *prevp;
while(cursor && ((bbp - cursor) <= max_dist)) {
prevlen = *(cursor - lzi->block_buf + lentab);
if (cursor[maxlen] == ch) {
*prevp = cursor;
(*lenp)++;
wasinc++;
break;
}
if (prevlen != maxlen) break;
cursor = *(cursor - lzi->block_buf + prevtab);
}
#ifdef DEBUG_PERF
tmptime = innerloop.ru_utime;
getrusage(RUSAGE_SELF, &innerloop);
timersub(&innerloop.ru_utime, &tmptime, &tmptime);
timeradd(&tmptime, &innertime, &innertime);
#endif
}
bbp--;
prevp--;
lenp--;
}
#ifdef DEBUG_PERF
tmptime = outerloop.ru_utime;
getrusage(RUSAGE_SELF, &outerloop);
timersub(&outerloop.ru_utime, &tmptime, &tmptime);
timeradd(&tmptime, &outertime, &outertime);
#endif
// fprintf(stderr, "maxlen = %d, wasinc = %ld\n", maxlen, wasinc);
}
#ifdef DEBUG_PERF
totaltime = totalloop.ru_utime;
getrusage(RUSAGE_SELF, &totalloop);
timersub(&totalloop.ru_utime, &totaltime, &totaltime);
fprintf(stderr, "Time spend in initial loop = %f\n", initialtime.tv_sec + initialtime.tv_usec/(double)1E6);
fprintf(stderr, "Time spend in outer loop = %f\n", outertime.tv_sec + outertime.tv_usec/(double)1E6);
fprintf(stderr, "Time spend in inner loop = %f\n", innertime.tv_sec + innertime.tv_usec/(double)1E6);
fprintf(stderr, "Time spend in all loops = %f\n", totaltime.tv_sec + totaltime.tv_usec/(double)1E6);
#endif
lzi->analysis_valid = 1;
#ifdef DEBUG_ANALYZE_BLOCK
fprintf(stderr, "Done analyzing block %d, cur_loc = %06x\n", n++, lzi->cur_loc);
#endif
}
void lz_stop_compressing(lz_info *lzi)
{
lzi->stop = 1;
/* fprintf(stderr, "Stopping...\n");*/
}
int lz_compress(lz_info *lzi, int nchars)
{
u_char *bbp, *bbe;
int *lentab, *lenp;
u_char **prevtab, **prevp;
int len;
int holdback;
short trimmed;
lzi->stop = 0;
while ((lz_left_to_process(lzi) || !lzi->eofcount) && !lzi->stop && nchars > 0) {
#if 1
if (!lzi->analysis_valid ||
(!lzi->eofcount &&
((lzi->chars_in_buf- lzi->block_loc) < nchars))) {
int residual = lzi->chars_in_buf - lzi->block_loc;
int bytes_to_move = lzi->max_dist + residual;
if (bytes_to_move > lzi->chars_in_buf)
bytes_to_move = lzi->chars_in_buf;
#ifdef DEBUG_ANALYZE_BLOCK
fprintf(stderr, "Moving %06x, chars_in_buf %06x, residual = %06x, nchars= %06x block_loc = %06x\n", bytes_to_move, lzi->chars_in_buf, residual, nchars, lzi->block_loc);
#endif
memmove(lzi->block_buf, lzi->block_buf + lzi->chars_in_buf - bytes_to_move,
bytes_to_move);
lzi->block_loc = bytes_to_move - residual;
lzi->chars_in_buf = bytes_to_move;
#ifdef DEBUG_ANALYZE_BLOCK
fprintf(stderr, "New chars_in_buf %06x, new block_loc = %06x, eof = %1d\n", lzi->chars_in_buf, lzi->block_loc, lzi->eofcount);
#endif
fill_blockbuf(lzi, nchars);
#ifdef DEBUG_ANALYZE_BLOCK
fprintf(stderr, "Really new chars_in_buf %06x, new block_loc = %06x, eof = %1d\n", lzi->chars_in_buf, lzi->block_loc, lzi->eofcount);
#endif
lz_analyze_block(lzi);
}
#else
if (!lzi->analysis_valid ||
(lzi->block_loc - lzi->chars_in_buf) == 0) {
lzi->block_loc = 0;
lzi->chars_in_buf = 0;
fill_blockbuf(lzi, nchars);
lz_analyze_block(lzi);
}
#endif
prevtab = prevp = lzi->prevtab + lzi->block_loc;
lentab = lenp = lzi->lentab + lzi->block_loc;
bbp = lzi->block_buf + lzi->block_loc;
holdback = lzi->max_match;
if (lzi->eofcount) holdback = 0;
if (lzi->chars_in_buf < (nchars + lzi->block_loc))
bbe = lzi->block_buf + lzi->chars_in_buf - holdback;
else
bbe = bbp + nchars;
while ((bbp < bbe) && (!lzi->stop)) {
trimmed = 0;
len = *lenp;
if (lzi->frame_size && (len > (lzi->frame_size - lzi->cur_loc % lzi->frame_size))) {
#ifdef DEBUG_TRIMMING
fprintf(stderr, "Trim for framing: %06x %d %d\n", lzi->cur_loc,len, (lzi->frame_size - lzi->cur_loc % lzi->frame_size));
#endif
trimmed = 1;
len = (lzi->frame_size - lzi->cur_loc % lzi->frame_size);
}
if (len > nchars) {
#ifdef DEBUG_TRIMMING
fprintf(stderr, "Trim for blocking: %06x %d %d\n", lzi->cur_loc,len, nchars);
#endif
trimmed = 1;
len = nchars;
}
if (len >= lzi->min_match) {
#ifdef LAZY
if ((bbp < bbe -1) && !trimmed &&
((lenp[1] > (len + 1)) /* || ((lenp[1] == len) && (prevp[1] > prevp[0])) */)) {
len = 1;
/* this is the lazy eval case */
}
else
#endif
if (lzi->output_match(lzi, (*prevp - lzi->block_buf) - lzi->block_loc,
len) < 0) {
// fprintf(stderr, "Match rejected: %06x %d\n", lzi->cur_loc, len);
len = 1; /* match rejected */
}
}
else
len = 1;
if (len < lzi->min_match) {
assert(len == 1);
lzi->output_literal(lzi, *bbp);
}
// fprintf(stderr, "len = %3d, *lenp = %3d, cur_loc = %06x, block_loc = %06x\n", len, *lenp, lzi->cur_loc, lzi->block_loc);
bbp += len;
prevp += len;
lenp += len;
lzi->cur_loc += len;
lzi->block_loc += len;
assert(nchars >= len);
nchars -= len;
}
}
return 0;
}

View file

@ -0,0 +1,60 @@
/*
File lz_nonslide.h, part of lzxcomp library
Copyright (C) 2002 Matthew T. Russotto
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; version 2.1 only
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef struct lz_info lz_info;
typedef int (*get_chars_t)(lz_info *lzi, int n, u_char *buf);
typedef int (*output_match_t)(lz_info *lzi, int match_pos, int match_len);
typedef void (*output_literal_t)(lz_info *lzi, u_char ch);
struct lz_info
{
int wsize; /* window size in bytes */
int max_match; /* size of longest match in bytes */
int min_match;
u_char *block_buf;
u_char *block_bufe;
int block_buf_size;
int chars_in_buf;
int cur_loc; /* location within stream */
int block_loc;
int frame_size;
int max_dist;
u_char **prevtab;
int *lentab;
short eofcount;
short stop;
short analysis_valid;
get_chars_t get_chars;
output_match_t output_match;
output_literal_t output_literal;
void *user_data;
};
void lz_init(lz_info *lzi, int wsize, int max_dist,
int max_match, int min_match,
int frame_size,
get_chars_t get_chars,
output_match_t output_match,
output_literal_t output_literal, void *user_data);
void lz_release(lz_info *lzi);
void lz_reset(lz_info *lzi);
void lz_stop_compressing(lz_info *lzi);
int lz_left_to_process(lz_info *lzi); /* returns # chars read in but unprocessed */
int lz_compress(lz_info *lzi, int nchars);

View file

@ -0,0 +1,42 @@
/*
File lzx_compress.h, part of lzxcomp library
Copyright (C) 2002 Matthew T. Russotto
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; version 2.1 only
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
typedef struct lzx_data lzx_data;
typedef int (*lzx_get_bytes_t)(void *arg, int n, void *buf);
typedef int (*lzx_put_bytes_t)(void *arg, int n, void *buf);
typedef void (*lzx_mark_frame_t)(void *arg, uint32_t uncomp, uint32_t comp);
typedef int (*lzx_at_eof_t)(void *arg);
typedef struct lzx_results
{
/* add more here? Error codes, # blocks, # frames, etc? */
long len_compressed_output;
long len_uncompressed_input;
} lzx_results;
int lzx_init(struct lzx_data **lzxdp, int wsize_code,
lzx_get_bytes_t get_bytes, void *get_bytes_arg,
lzx_at_eof_t at_eof,
lzx_put_bytes_t put_bytes, void *put_bytes_arg,
lzx_mark_frame_t mark_frame, void *mark_frame_arg);
void lzx_reset(lzx_data *lzxd);
int lzx_compress_block(lzx_data *lzxd, int block_size, int subdivide);
int lzx_finish(struct lzx_data *lzxd, struct lzx_results *lzxr);

View file

@ -0,0 +1,4 @@
#if BYTE_ORDER == BIG_ENDIAN
#define LZX_BIG_ENDIAN
#endif

View file

@ -0,0 +1,40 @@
/*
File lzx_constants.h, part of lzxcomp library
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; version 2.1 only
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--------------------------------------
The above lines apply to the lzxcomp library as a whole. This file,
lzx_constants.h, however, is probably uncopyrightable, and in any
case I explicitly place it in the public domain.
Matthew T. Russotto
*/
/* these named constants are from the Microsoft LZX documentation */
#define MIN_MATCH 2
#define MAX_MATCH 257
#define NUM_CHARS 256
#define NUM_PRIMARY_LENGTHS 7
#define NUM_SECONDARY_LENGTHS 249
/* the names of these constants are specific to this library */
#define LZX_MAX_CODE_LENGTH 16
#define LZX_FRAME_SIZE 32768
#define LZX_PRETREE_SIZE 20
#define LZX_ALIGNED_BITS 3
#define LZX_ALIGNED_SIZE 8
#define LZX_VERBATIM_BLOCK 1
#define LZX_ALIGNED_OFFSET_BLOCK 2

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
// This file is part of hhpcomp, a free HTML Help Project (*.hhp) compiler.
// Copyright (C) 2015 Benedikt Freisen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <string>
#include <algorithm>
#include <stdexcept>
#include <unistd.h>
#include <stdlib.h>
using namespace std;
string to_upper(string s)
{
string temp = s;
transform(temp.begin(), temp.end(), temp.begin(), ::toupper);
return temp;
}
string realpath(const char* path)
{
char* temp = realpath(path, NULL);
if (temp == NULL)
throw runtime_error("realpath failed");
string result(temp);
free(temp);
return result;
}
string replace_backslashes(string s)
{
string temp = s;
for (string::iterator it = temp.begin(); it != temp.end(); ++it)
if (*it == '\\')
*it = '/';
return temp;
}

View file

@ -0,0 +1,24 @@
// This file is part of hhpcomp, a free HTML Help Project (*.hhp) compiler.
// Copyright (C) 2015 Benedikt Freisen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
string to_upper(string s);
string realpath(const char* path);
string replace_backslashes(string s);