Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

open-axiom repository from github

24005 views
1
/*
2
Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.
3
All rights reserved.
4
Copyright (C) 2007-2010, Gabriel Dos Reis.
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are
9
met:
10
11
- Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
14
- Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in
16
the documentation and/or other materials provided with the
17
distribution.
18
19
- Neither the name of The Numerical Algorithms Group Ltd. nor the
20
names of its contributors may be used to endorse or promote products
21
derived from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
/* HyperDoc database file manager */
37
38
39
#include "openaxiom-c-macros.h"
40
41
#include <errno.h>
42
#include <setjmp.h>
43
#include <stdlib.h>
44
#include <sys/stat.h>
45
#include <stdlib.h>
46
#include <string.h>
47
#include <locale.h>
48
49
#include "cfuns.h"
50
#include "hash.h"
51
#include "lex.h"
52
#include "sockio.h"
53
#include "addfile.h"
54
#include "node.h"
55
56
/* FIXME: Remove this kludge */
57
using namespace OpenAxiom;
58
59
static void add_file(char*, char*, int);
60
static void add_new_pages(FILE*, FILE*, char*, char*);
61
static int build_db_filename(short, char*, char*);
62
static void delete_db(FILE*, FILE*, char*);
63
static int delete_file(char*, char*);
64
static void get_filename();
65
static void parse_args(char**, char*, char**, short*);
66
static void update_db(FILE*, FILE*, FILE*, char*, char*, int);
67
68
69
70
/*
71
* These are variables that htadd needs to have declared because it shares
72
* the lexical analyzer with HyperDoc
73
*/
74
75
int gTtFontIs850=0;
76
HDWindow *gWindow = NULL;
77
extern int line_number; /* keeps track of which line a page starts on
78
* in a file. This way someone can start
79
* including a line number counter into
80
* HyperDoc. */
81
int fresh = 0;
82
83
#define Delete 1
84
#define System 2
85
#define Current 4
86
#define Named 8
87
88
#define usage "usage: htadd [-s|-l|-f db-directory] [-d|-n] filenames"
89
90
91
int
92
main(int argc, char **argv)
93
{
94
using namespace OpenAxiom;
95
/*int i;*/
96
char db_dir[256]; /* the directory where the db file is */
97
char dbfilename[256]; /* the database filename */
98
char *filenames[1000]; /* the files to be added */
99
char **fnames = filenames;
100
short flag; /* flag for deleting or adding */
101
102
oa_setenv("LC_ALL", "C");
103
setlocale(LC_ALL, "");
104
parse_args(argv, db_dir, filenames, &flag);
105
106
if (!filenames[0]) {
107
fprintf(stderr, "%s\n", usage);
108
return -1;
109
}
110
111
parser_init();
112
113
build_db_filename(flag, db_dir, dbfilename);
114
115
if (fresh)
116
oa_unlink(dbfilename);
117
118
if (flag & Delete)
119
while (*fnames)
120
delete_file(dbfilename, *fnames++);
121
else
122
while (*fnames)
123
add_file(dbfilename, *fnames++, fresh);
124
return 0;
125
}
126
127
/*
128
* This routine parses the command line arguments. It parses
129
* the command line arguments. It returns a flag which tells the calling
130
* routine what database file to use, and whether or not to delete files.
131
*/
132
133
134
static void
135
parse_args(char **argv, char *db_dir, char **filenames, short *fl)
136
{
137
*fl = 0;
138
139
while (*++argv) {
140
if (strcmp(*argv, "-d") == 0)
141
*fl |= Delete;
142
else if (strcmp(*argv, "-s") == 0) {
143
if (*fl & Current || *fl & Named) {
144
fprintf(stderr, "%s\n", usage);
145
exit(-1);
146
}
147
*fl |= System;
148
}
149
else if (strcmp(*argv, "-n") == 0) {
150
fresh = 1;
151
}
152
else if (strcmp(*argv, "-l") == 0) {
153
if (*fl & System || *fl & Named) {
154
fprintf(stderr, "%s\n", usage);
155
exit(-1);
156
}
157
*fl |= Current;
158
}
159
else if (strcmp(*argv, "-f") == 0) {
160
if (*fl & System || *fl & Current) {
161
fprintf(stderr, "%s\n", usage);
162
exit(-1);
163
}
164
*fl |= Named;
165
strcpy(db_dir, *++argv);
166
}
167
else
168
*filenames++ = *argv;
169
}
170
171
*filenames = NULL;
172
}
173
174
175
176
/* check to see if the user has permission */
177
178
/*
179
* This procedure builds the db filename. Subsequently, it is passed onto all
180
* the add files that are called.
181
*/
182
183
184
static int
185
build_db_filename(short flag, char *db_dir, char *dbfilename)
186
{
187
int ret_status;
188
char *SPAD;
189
struct stat buff;
190
char path[256];
191
192
193
if (flag & System) {
194
SPAD = oa_getenv("AXIOM");
195
if (SPAD == NULL) {
196
fprintf(stderr,
197
"build_db_filename: cannot find system root directory\n");
198
exit(-1);
199
}
200
sprintf(dbfilename, "%s/share/hypertex/pages/%s", SPAD, db_file_name);
201
sprintf(path, "%s/share/hypertex/pages", SPAD);
202
}
203
else if (flag & Named) {
204
sprintf(dbfilename, "%s/%s", db_dir, db_file_name);
205
strcpy(path, db_dir);
206
}
207
else { /* use the current directory */
208
sprintf(dbfilename, "./%s", db_file_name);
209
sprintf(path, "./");
210
}
211
/* fprintf(stderr,"htadd:build_db_filename:dbfilename=%s\n",dbfilename);*/
212
/* Now see if I can write to the file */
213
errno = 0;
214
ret_status = stat(dbfilename, &buff);
215
if (ret_status == -1) {
216
if (errno == ENOENT)
217
/* If the file does not exist, check the path. */
218
ret_status = stat(path, &buff);
219
if (ret_status == -1) {
220
perror("build_db_file");
221
exit(1);
222
}
223
}
224
225
if (writeablep(dbfilename) > 0)
226
return 1;
227
228
fprintf(stderr, "build_db_filename: '%s' is not writable\n",dbfilename);
229
exit(1);
230
return 0;
231
}
232
233
234
/***
235
236
This procedure now works as follows:
237
(1) It adds the files to the db_file without full pathnames.
238
Two names are going to be used when adding a file -
239
addname <-- The name without any paths
240
fullname <-- The name with a path prepended to it
241
(2) If the user specifies a pathname, then it is the path name that
242
is used. If the user does not dpecify a path name, then possible
243
paths are found as follows:
244
(i) If the user has an environment variable HTPATH set, the
245
paths mentioned are used.
246
(ii) If not, then the $AXIOM environment variable is used.
247
****/
248
249
static void
250
add_file(char *dbname, char *name, int fresh)
251
{
252
char fullname[256];
253
char temp_db_file[256];
254
FILE *db_fp = NULL;
255
FILE *temp_db_fp = NULL;
256
FILE *ht_fp = NULL;
257
char addname[100];
258
/*char *HTPATH;*/
259
/*char *trace;*/
260
/*char *spad;*/
261
262
263
/** First thing I should do is find the proper file and open it **/
264
ht_fp = ht_file_open(fullname, addname, name);
265
266
/*
267
* Now I should try to open the two database files. The one to work with,
268
* and the temporary one; Send it a 1 so it checks for write access
269
*/
270
if (fresh) {
271
if ((db_fp = fopen(dbname, "a")) == NULL) {
272
fprintf(stderr, "Can't open database: %s file for appending\n", dbname);
273
exit(-1);
274
}
275
}
276
else {
277
if ((db_fp = fopen(dbname, "r")) == NULL) {
278
exit(-1);
279
}
280
}
281
if (!fresh)
282
temp_db_fp = temp_file_open(temp_db_file);
283
284
/** Now actually update the file by adding the changes ***/
285
update_db(db_fp, temp_db_fp, ht_fp, addname, fullname, fresh);
286
287
if (!fresh)
288
fclose(temp_db_fp);
289
fclose(ht_fp);
290
if (db_fp != NULL)
291
fclose(db_fp);
292
if (!fresh) {
293
if (oa_copy_file(temp_db_file, dbname) < 0)
294
exit(-1);
295
unlink(temp_db_file);
296
}
297
}
298
299
static void
300
update_db(FILE *db, FILE *temp_db, FILE *new_file,
301
char *addname, char *fullname, int fresh)
302
{
303
char *fname;
304
int c, file_there = 0, mtime;
305
306
if (fresh) {
307
add_new_pages(db, new_file, addname, fullname);
308
return;
309
}
310
if (db == NULL) {
311
add_new_pages(temp_db, new_file, addname, fullname);
312
return;
313
}
314
init_scanner();
315
cfile = db;
316
c = get_char();
317
do {
318
if (c == '\t') {
319
get_filename();
320
fname = alloc_string(token.id);
321
get_token();
322
mtime = atoi(token.id);
323
if (strcmp(fname, addname) == 0) {
324
save_scanner_state();
325
add_new_pages(temp_db, new_file, addname, fullname);
326
restore_scanner_state();
327
file_there = 1;
328
while ((c = get_char()) != EOF) {
329
if (c == '\t')
330
break;
331
}
332
}
333
else {
334
fprintf(temp_db, "\t%s %d", fname, mtime);
335
while ((c = get_char()) != EOF) {
336
if (c == '\t')
337
break;
338
putc(c, temp_db);
339
}
340
}
341
free(fname);
342
}
343
else
344
c = get_char();
345
} while (c != EOF);
346
if (!file_there) {
347
add_new_pages(temp_db, new_file, addname, fullname);
348
}
349
}
350
351
#define Special(t) \
352
(( t == openaxiom_Page_token \
353
|| t == openaxiom_NewCommand_token \
354
|| t == openaxiom_Patch_token )?(1):(0))
355
#define ptype(c, t) (strcpy(c, t));
356
357
static void
358
add_new_pages(FILE *temp_db, FILE *new_file, char *addname, char *fullname)
359
{
360
char type[15];
361
int pos;
362
int present_type;
363
int pages = 0;
364
struct stat fstats;
365
366
stat(fullname, &fstats);
367
fprintf(temp_db, "\t%s %d\n", addname, (int)fstats.st_mtime);
368
cfile = new_file;
369
init_scanner();
370
while (get_token() != EOF) {
371
if (Special(token.type)) {
372
ptype(type, token.id);
373
present_type = token.type;
374
pos = keyword_fpos;
375
get_token();
376
if (token.type != openaxiom_Lbrace_token) {
377
fprintf(stderr, "missing left brace after a page, macro or patch \
378
declaration\n");
379
fprintf(stderr, "In the file %s on line %d\n", fullname, line_number);
380
exit(-1);
381
}
382
get_token();
383
if (present_type == openaxiom_Page_token
384
&& token.type != openaxiom_Word_token) {
385
fprintf(stderr, "missing page name after \\begin{page}\n");
386
fprintf(stderr, "In the file %s on line %d\n", fullname, line_number);
387
exit(-1);
388
}
389
else if (present_type == openaxiom_Macro_token
390
&& token.type != openaxiom_Macro_token) {
391
fprintf(stderr, "Expected a \\macro name after newcommand, got %s\n",
392
token.id);
393
fprintf(stderr, "In the file %s on line %d\n", fullname, line_number);
394
exit(-1);
395
}
396
else if (present_type == openaxiom_Patch_token
397
&& token.type != openaxiom_Word_token) {
398
fprintf(stderr, "Missing patch name after a \\begin{patch}\n");
399
fprintf(stderr, "In the file %s on line %d\n", fullname, line_number);
400
exit(-1);
401
}
402
fprintf(temp_db, "\\%s %s %d %d\n", type,
403
token.id, pos, line_number);
404
pages++;
405
}
406
}
407
printf("Added %3d pages and/or macros from %s\n", pages, addname);
408
}
409
410
#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
411
#define delim(c) \
412
(whitespace(c) )
413
414
415
static void
416
get_filename()
417
{
418
int c, ws;
419
static char buffer[256];
420
char *buf = buffer;
421
422
do {
423
keyword_fpos = fpos;
424
c = get_char();
425
ws = whitespace(c);
426
} while (ws);
427
switch (c) {
428
case EOF:
429
fprintf(stderr, "Error trying to read ht.db, unexpected EOF\n");
430
exit(-1);
431
case '%':
432
case '\\':
433
case '{':
434
case '}':
435
fprintf(stderr, "Error unexpexted character %c\n",c);
436
exit(-1);
437
default:
438
do {
439
*buf++ = c;
440
} while ((c = get_char()) != EOF && !delim(c));
441
unget_char(c);
442
*buf = '\0';
443
token.type = openaxiom_Word_token;
444
token.id = buffer;
445
break;
446
}
447
}
448
449
static int
450
delete_file(char *dbname, char *name)
451
{
452
char temp_db_file[256];
453
FILE *db_fp, *temp_db_fp;
454
char dname[256];
455
456
457
strcpy(dname, name);
458
extend_ht(dname);
459
460
/* Open both the tmp database and the real one */
461
if ((db_fp = fopen(dbname, "r")) == NULL) {
462
fprintf(stderr, "database file is empty, nothing to delete\n");
463
return 1;
464
}
465
466
temp_db_fp = temp_file_open(temp_db_file);
467
468
/** Now actually update the file by deleting the pages */
469
delete_db(db_fp, temp_db_fp, dname);
470
471
fclose(temp_db_fp);
472
if (db_fp != NULL)
473
fclose(db_fp);
474
if (oa_copy_file(temp_db_file, dbname) < 0)
475
return -1;
476
unlink(temp_db_file);
477
return 0;
478
}
479
480
static void
481
delete_db(FILE *db, FILE *temp_db, char *name)
482
{
483
char *fname;
484
int c/*, file_there = 0*/, mtime;
485
486
init_scanner();
487
cfile = db;
488
c = get_char();
489
do {
490
if (c == '\t') {
491
get_filename();
492
fname = alloc_string(token.id);
493
get_token();
494
mtime = atoi(token.id);
495
if (strcmp(fname, name) == 0) {
496
while ((c = get_char()) != EOF) {
497
if (c == '\t')
498
break;
499
}
500
}
501
else {
502
fprintf(temp_db, "\t%s %d", fname, mtime);
503
while ((c = get_char()) != EOF) {
504
if (c == '\t')
505
break;
506
putc(c, temp_db);
507
}
508
}
509
free(fname);
510
}
511
else
512
c = get_char();
513
} while (c != EOF);
514
}
515
516