#include "openaxiom-c-macros.h"
#include "debug.h"
#include "halloc.h"
#include "sockio.h"
#include "parse.h"
#include "addfile.h"
#include "lex.h"
#include "hyper.h"
static void read_ht_file(HashTable * page_hash , HashTable * macro_hash , HashTable * patch_hash , FILE * db_fp , char * db_file);
static HyperDocPage * make_special_page(int type , const char * name);
extern int make_input_file;
extern int gverify_dates;
InputBox *rb_list;
InputBox *end_rb_list;
HashTable ht_gFileHashTable;
#define htfhSize 100
int
window_equal(Window *w1, Window *w2)
{
return *w1 == *w2;
}
int
window_code(Window *w, int size)
{
return (*w) % size;
}
char *
window_id(Window w)
{
char *ret;
char buff[32];
int length;
sprintf(buff, "%ld", w);
length = strlen(buff);
ret = (char *) halloc(length * sizeof(char) + 1, "windowid");
strcpy(ret, buff);
return (ret);
}
void
read_ht_db(HashTable *page_hash, HashTable *macro_hash, HashTable *patch_hash)
{
FILE *db_fp;
char db_file[256];
int i = 0;
gDatabasePath = NULL;
hash_init(
page_hash,
PageHashSize,
(EqualFunction) string_equal,
(HashcodeFunction) string_hash);
hash_init(
macro_hash,
MacroHashSize,
(EqualFunction) string_equal,
(HashcodeFunction) string_hash);
hash_init(
patch_hash,
PatchHashSize,
(EqualFunction) string_equal,
(HashcodeFunction) string_hash);
hash_init(
&ht_gFileHashTable,
htfhSize,
(EqualFunction) string_equal,
(HashcodeFunction) string_hash);
while ((db_fp = db_file_open(db_file)) != NULL) {
i++;
read_ht_file(page_hash, macro_hash, patch_hash, db_fp, db_file);
fclose(db_fp);
}
if (!i) {
fprintf(stderr,
"(HyperDoc) read_ht_db: No %s file found\n", db_file_name);
exit(-1);
}
free_hash(&ht_gFileHashTable, (FreeFunction)free_string);
}
static void
read_ht_file(HashTable *page_hash, HashTable *macro_hash,
HashTable *patch_hash, FILE *db_fp, char *db_file)
{
char filename[256];
char *fullname = filename;
UnloadedPage *page;
MacroStore *macro;
PatchStore *patch;
int pages = 0, c, mtime, ret_val;
struct stat fstats;
cfile = db_fp;
init_scanner();
ret_val = strlen(db_file) - 1;
for (; ret_val >= 0; ret_val--)
if (db_file[ret_val] == '/') {
db_file[ret_val] = '\0';
break;
}
c = getc(db_fp);
do {
if (c == '\t') {
get_filename();
fullname = alloc_string(token.id);
if (fullname[0] != '/') {
strcpy(filename, db_file);
strcat(filename, "/");
strcat(filename, fullname);
free(fullname);
fullname = alloc_string(filename);
}
while (hash_find(&ht_gFileHashTable, fullname) != NULL) {
do {
c = getc(db_fp);
} while ((c != EOF) && (c != '\t'));
if (c == EOF)
return;
get_filename();
fullname = alloc_string(token.id);
if (fullname[0] != '/') {
strcpy(filename, db_file);
strcat(filename, "/");
strcat(filename, fullname);
free(fullname);
fullname = alloc_string(filename);
}
}
hash_insert(&ht_gFileHashTable, fullname, fullname);
ret_val = stat(fullname, &fstats);
if (ret_val == -1) {
char buffer[300];
sprintf(buffer, "(HyperDoc) read_ht_db: Unable To Open %s :", fullname);
perror(buffer);
exit(-1);
}
get_token();
mtime = atoi(token.id);
if (gverify_dates & (fstats.st_mtime > mtime)) {
fprintf(stderr, "(HyperDoc) read_ht_file: HyperDoc file %s has been updated\n",
fullname);
fprintf(stderr, "(HyperDoc) Issue htadd %s to update database\n", fullname);
exit(-1);
}
while ((c = getc(db_fp)) != EOF) {
if (c == '\t')
break;
ungetc(c, db_fp);
get_token();
switch (token.type) {
case openaxiom_Page_token:
get_token();
page = (UnloadedPage *) halloc(sizeof(UnloadedPage),
"UnloadedPage");
page->fpos.name = alloc_string(fullname);
page->name = alloc_string(token.id);
get_token();
if (hash_find(page_hash, page->name) != NULL) {
fprintf(stderr, "(HyperDoc) Page name %s occurred twice\n", page->name);
fprintf(stderr, "(HyperDoc) The Version in %s is being ignored \n",
page->fpos.name);
free(page);
get_token();
break;
}
page->fpos.pos = atoi(token.id);
get_token();
page->fpos.ln = atoi(token.id);
page->type = UnloadedPageType;
hash_insert(page_hash, (char *)page, page->name);
pages++;
break;
case openaxiom_NewCommand_token:
get_token();
macro = (MacroStore *) halloc(sizeof(MacroStore), "MacroStore");
macro->fpos.name = alloc_string(fullname);
macro->name = alloc_string(token.id);
macro->macro_string = NULL;
get_token();
if (hash_find(macro_hash, macro->name) != NULL) {
if (strcmp(macro->name, "localinfo") != 0) {
fprintf(stderr, "(HyperDoc) Macro name %s occurred twice\n",
macro->name);
fprintf(stderr, "(HyperDoc) The Version in %s is being ignored \n",
macro->fpos.name);
}
get_token();
free(macro);
break;
}
macro->fpos.pos = atoi(token.id);
get_token();
macro->fpos.ln = atoi(token.id);
macro->loaded = 0;
hash_insert(macro_hash, (char *)macro, macro->name);
break;
case openaxiom_Patch_token:
get_token();
patch = (PatchStore *) alloc_patchstore();
patch->fpos.name = alloc_string(fullname);
patch->name = alloc_string(token.id);
get_token();
patch->fpos.pos = atoi(token.id);
get_token();
patch->fpos.ln = atoi(token.id);
if (hash_find(patch_hash, patch->name) != NULL) {
fprintf(stderr, "(HyperDoc) Patch name %s occurred twice\n", patch->name);
fprintf(stderr, "(HyperDoc) The version in %s is being ignored \n",
patch->fpos.name);
free_patch(patch);
break;
}
hash_insert(patch_hash, (char *)patch, patch->name);
break;
default:
fprintf(stderr, "(HyperDoc) read_ht_db: Unknown type %s in ht.db\n", token.id);
exit(-1);
break;
}
}
}
else
c = getc(db_fp);
} while (c != EOF);
}
HyperLink *
make_link_window(TextNode *link_node, int type, int isSubWin)
{
HyperLink *link;
XSetWindowAttributes at;
if (make_input_file)
switch (type) {
case openaxiom_Downlink_token:
case openaxiom_Memolink_token:
case openaxiom_Windowlink_token: {
char *name;
HyperDocPage *p;
name = print_to_string(link_node);
p = (HyperDocPage *) hash_find(gWindow->fPageHashTable, name);
if (!p)
printf("undefined link to %s\n", name);
break;
}
}
else {
link = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
if (link == NULL) {
fprintf(stderr, "(HyperDoc) Ran out of memory allocating a hypertext link!\n");
exit(-1);
}
at.cursor = gActiveCursor;
at.event_mask = ButtonPress;
if (isSubWin)
link->win = XCreateWindow(gXDisplay, gWindow->fDisplayedWindow, 0, 0, 100, 100, 0,
0, InputOnly, CopyFromParent,
CWEventMask | CWCursor, &at);
else
link->win = 0;
link->type = type;
link->x = link->y = 0;
link->reference.node = link_node;
hash_insert(gLinkHashTable, (char *)link,(char *)&link->win);
return link;
}
return 0;
}
HyperLink *
make_paste_window(PasteNode *paste)
{
HyperLink *link;
XSetWindowAttributes at;
if (!make_input_file) {
link = (HyperLink *) halloc(sizeof(HyperLink), "HyperLink");
if (link == NULL) {
fprintf(stderr, "(HyperDoc) Ran out of memory allocating a hypertext link!\n");
exit(-1);
}
at.cursor = gActiveCursor;
at.event_mask = ButtonPress;
link->win = XCreateWindow(gXDisplay, gWindow->fDisplayedWindow,
0, 0, 100, 100, 0,
0, InputOnly, CopyFromParent,
CWEventMask | CWCursor, &at);
link->type = openaxiom_Pastebutton_token;
link->x = link->y = 0;
link->reference.paste = paste;
hash_insert(gLinkHashTable, (char *)link,(char *) &link->win);
return link;
}
return 0;
}
static HyperDocPage *
make_special_page(int type, const char *name)
{
HyperDocPage *page = alloc_page(name);
if (page == NULL) {
fprintf(stderr, "(HyperDoc) Ran out of memory allocating page.\n");
exit(-1);
}
page->type = type;
free(page->fLinkHashTable);
page->fLinkHashTable = NULL;
return page;
}
void
make_special_pages(HashTable *pageHashTable)
{
hash_insert(pageHashTable,
(char *)make_special_page(openaxiom_Quitbutton_token,
"QuitPage"),
"QuitPage");
hash_insert(pageHashTable,
(char *)make_special_page(openaxiom_Returnbutton_token,
"ReturnPage"),
"ReturnPage");
hash_insert(pageHashTable,
(char *)make_special_page(openaxiom_Upbutton_token, "UpPage"),
"UpPage");
}
void
add_dependencies()
{
TextNode *bound_node = curr_node;
TextNode *node;
SpadcomDepend *depend;
if (cur_spadcom == NULL) {
fprintf(stderr, "(HyperDoc) \\bound occuring outside a \\spadcom\n");
print_page_and_filename();
exit(-1);
}
curr_node->type = openaxiom_Bound_token;
curr_node->data.node = alloc_node();
curr_node = curr_node->data.node;
get_expected_token(openaxiom_Lbrace_token);
parse_HyperDoc();
curr_node->type = openaxiom_Endarg_token;
curr_node = bound_node;
if (gPageBeingParsed->depend_hash == NULL) {
gPageBeingParsed->depend_hash =
(HashTable *) halloc(sizeof(HashTable), "Hash Table");
hash_init(
gPageBeingParsed->depend_hash,
DependHashSize,
(EqualFunction) string_equal,
(HashcodeFunction) string_hash);
}
for (node = bound_node->data.node;
node->type != openaxiom_Endarg_token;
node = node->next) {
if (node->type == openaxiom_Word_token) {
depend = (SpadcomDepend *) halloc(sizeof(SpadcomDepend), "SpadcomDepend");
depend->label = alloc_string(node->data.text);
depend->spadcom = cur_spadcom;
depend->executed = 0;
hash_insert(gPageBeingParsed->depend_hash, (char *)depend, depend->label);
}
}
}
int
is_number(const char * str)
{
const char *s;
for (s = str; *s != '\0'; s++) {
if (!(isdigit(*s) || *s == '-'))
return 0;
}
return 1;
}
void
parser_error(char *str)
{
int i, v;
fprintf(stderr, " %s\n", str);
fprintf(stderr, "Here are the next 10 tokens:\n");
for (i = 0; i < 10; i++) {
v = get_token();
if (v == EOF)
break;
print_token();
}
fprintf(stderr, "\n");
exit(-1);
}
#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
#define delim(c) \
(whitespace(c))
int
get_filename()
{
int c, ws;
static int seen_white = 0;
static char buffer[256];
char *buf = buffer;
if (last_token) {
last_token = 0;
return 0;
}
do {
keyword_fpos = fpos;
c = get_char();
ws = whitespace(c);
if (ws)
seen_white = 1;
} while (ws);
switch (c) {
case EOF:
fprintf(stderr, "(HyperDoc) Error trying to read %s, unexpected end-of-file.\n",db_file_name);
exit(-1);
case '%':
case '\\':
case '{':
case '}':
fprintf(stderr, "(HyperDoc) Error unexpected character %c.\n",c);
exit(-1);
default:
do {
*buf++ = c;
} while ((c = get_char()) != EOF && !delim(c));
unget_char(c);
*buf = '\0';
token.type = openaxiom_Word_token;
token.id = buffer;
seen_white = 0;
break;
}
return 1;
}
char *
get_input_string()
{
char *string;
TextNode *string_node,*save_node;
save_node = curr_node;
string_node = alloc_node();
curr_node = string_node;
parse_HyperDoc();
curr_node->type = openaxiom_Endarg_token;
string = print_to_string(string_node);
free_node(string_node, 0);
curr_node=save_node;
return string;
}
SourceInputKind
get_where()
{
SourceInputKind tw;
get_token();
if (token.type != openaxiom_Word_token)
return SourceInputKind::Error;
if (!strcmp(token.id, "lisp")) {
tw = SourceInputKind::SpadSocket;
}
else if (!strcmp(token.id, "unix")) {
tw = SourceInputKind::UnixFD;
}
else if (!strcmp(token.id, "ht")) {
tw = SourceInputKind::File;
}
else {
return SourceInputKind::Error;
}
get_token();
if (token.type != openaxiom_Rsquarebrace_token)
return SourceInputKind::Error;
return tw;
}
FILE *
find_fp(FilePosition fp)
{
FILE *lfile;
char fullname[256], addname[256];
int ret_val;
lfile = (FILE *) hash_find(&gFileHashTable, fp.name);
if (lfile == NULL) {
lfile = ht_file_open(fullname, addname, fp.name);
hash_insert(&gFileHashTable, (char *)lfile, fp.name);
}
ret_val = fseek(lfile, fp.pos, 0);
if (ret_val == -1) {
perror("fseeking to a page");
longjmp(jmpbuf, 1);
}
page_start_fpos = fp.pos;
line_number = fp.ln;
return lfile;
}