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-2012, 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
/*
37
* hthits pattern htdb-file
38
*
39
* Scan HyperDoc files for a given pattern.
40
*
41
* The output contains lines of the form:
42
*
43
* page-name`title`n
44
*
45
* The title and body of each page are scanned but the name is not. It is
46
* possible that the title matches but not any lines. The number of matches
47
* in the page (n) is given last.
48
*
49
* SMW Feb 91
50
*/
51
52
#include "openaxiom-c-macros.h"
53
54
#include "debug.h"
55
56
#include <stdlib.h>
57
#include <stdio.h>
58
#include <string.h>
59
#include <ctype.h>
60
#include <sys/types.h>
61
#include <sys/stat.h>
62
#include <regex.h>
63
#include <locale.h>
64
65
#include "cfuns.h"
66
67
/*
68
* For fixed-size arrays.
69
*/
70
#define MAX_HTDB_LINE 1024
71
#define MAX_ENTRY_TYPE 30 /* I.e. \page \newcommand \patch ... */
72
#define MAX_ENTRY_NAME 1024 /* E.g. DifferentialCalculusPage */
73
#define MAX_COMP_REGEX 1024
74
75
typedef struct PgInfo {
76
char name[MAX_ENTRY_NAME];
77
long start, size;
78
} PgInfo ;
79
80
/*
81
* Global variables set according to the command line.
82
*/
83
84
char *progName;
85
char *pattern;
86
char *htdbFName;
87
int gverifydates=0;
88
regex_t reg_pattern;
89
90
static void
91
badDB()
92
{
93
fprintf(stderr, "%s: bad database file %s\n", progName, htdbFName);
94
exit(1);
95
}
96
97
98
static void
99
untexbuf(register char* s)
100
{
101
char *d = s;
102
103
while (*s)
104
switch (*s) {
105
case '\\':
106
*d++ = ' ';
107
s++;
108
if (*s != '%')
109
while (isalpha(*s))
110
s++;
111
break;
112
case '%':
113
*d++ = ' ';
114
s++;
115
while (*s && *s != '\n')
116
s++;
117
break;
118
case '{':
119
case '}':
120
case '#':
121
*d++ = ' ';
122
s++;
123
break;
124
default:
125
*d++ = *s++;
126
}
127
*d = 0;
128
}
129
130
131
/*
132
* Any newlines and separator characters in the title are changed to blanks.
133
*/
134
135
static void
136
splitpage(char* buf, char** ptitle, char** pbody)
137
{
138
int n, depth, tno;
139
char* s;
140
141
switch (buf[1]) {
142
case 'p':
143
tno = 2;
144
break; /* \page{Name}{Title} */
145
case 'b':
146
tno = 3;
147
break; /* \begin{page}{Name}{Title} */
148
default:
149
fprintf(stderr, "%s: Invalid page format: %s\n", progName, buf);
150
exit(1);
151
}
152
153
n = 0;
154
depth = 0;
155
156
for (s = buf; *s; s++) {
157
if (*s == '{')
158
if (++depth == 1 && ++n == tno)
159
*ptitle = s + 1;
160
if (*s == '}')
161
if (depth-- == 1 && n == tno) {
162
*s = 0;
163
*pbody = s + 1;
164
break;
165
}
166
}
167
}
168
169
170
/*
171
* Given string s and length n, output ` followed by the first n characters
172
* of s with ` and newline converted to blanks. This function destructively
173
* modifies s.
174
*/
175
176
static void
177
squirt(char* s, int n)
178
{
179
char *t, *e;
180
int c;
181
182
c = s[n];
183
184
for (t = s, e = s + n; t < e; t++)
185
if (*t == '`' || *t == '\n')
186
*t = ' ';
187
188
if (s[n] != 0) {
189
s[n] = 0;
190
}
191
printf("{%.*s}", n, s);
192
s[n] = c;
193
}
194
195
static void
196
searchPage(char* pgname, char* pgtitle, char* pgbody)
197
{
198
char *bodyrest;
199
regmatch_t match_pos;
200
int nhits = 0;
201
202
if (!regexec(&reg_pattern, pgtitle, 1, &match_pos, 0))
203
nhits++;
204
205
bodyrest = pgbody;
206
while (!regexec(&reg_pattern, bodyrest, 1, &match_pos, 0)) {
207
nhits++;
208
bodyrest += match_pos.rm_eo;
209
}
210
if (nhits) {
211
printf("\\newsearchresultentry{%d}{%s}",nhits, pgtitle);
212
squirt(pgname, strlen(pgname));
213
printf("\n");
214
}
215
}
216
217
static void
218
handlePage(FILE* infile, PgInfo* pg)
219
{
220
static char *pgBuf = 0;
221
static int pgBufSize = 0;
222
223
char *title, *body;
224
225
if (pg->size > pgBufSize - 1) {
226
if (pgBuf)
227
free(pgBuf);
228
pgBufSize = pg->size + 20000;
229
pgBuf = (char *)malloc(pgBufSize);
230
231
if (!pgBuf) {
232
fprintf(stderr,"%s: Out of memory\n", progName);
233
exit(1);
234
}
235
}
236
237
fseek(infile, pg->start, 0);
238
fread(pgBuf, pg->size, 1, infile);
239
pgBuf[pg->size] = 0;
240
241
splitpage(pgBuf, &title, &body);
242
/*untexbuf(title);*/
243
untexbuf(body);
244
245
#ifdef DEBUG
246
printf("-------------- %s -------------\n%s", pg->name, pgBuf);
247
printf("============== %s =============\n", title);
248
printf("%s", body);
249
#endif
250
251
searchPage(pg->name, title, body);
252
}
253
254
static void
255
handleFilePages(const char* fname, int pgc, PgInfo* pgv)
256
{
257
FILE *infile;
258
int i;
259
260
infile = fopen(fname, "r");
261
if (infile == NULL) {
262
fprintf(stderr, "%s: Cannot read file %s\n", progName, fname);
263
exit(1);
264
}
265
266
for (i = 0; i < pgc; i++)
267
handlePage(infile, pgv + i);
268
269
fclose(infile);
270
}
271
272
static void
273
handleFile(FILE* htdbFile)
274
{
275
static PgInfo *pgInfoV = 0;
276
static int pgInfoC = 0;
277
278
char htdbLine[MAX_HTDB_LINE];
279
char htfname[MAX_HTDB_LINE];
280
time_t httime;
281
long htsize;
282
struct stat htstat;
283
284
long fstart, fend;
285
int rc, i, npages;
286
287
char entname[MAX_ENTRY_NAME], enttype[MAX_ENTRY_TYPE];
288
long entoffset, entlineno;
289
290
fgets(htdbLine, MAX_HTDB_LINE, htdbFile);
291
292
sscanf(htdbLine, " %s %ld", htfname, &httime);
293
294
/*
295
* 1. Verify file: get size and check modification time.
296
*/
297
rc = stat(htfname, &htstat);
298
if (rc == -1) {
299
fprintf(stderr, "%s: Cannot access %s\n", progName, htfname);
300
exit(1);
301
}
302
if (gverifydates && (htstat.st_mtime != httime)) {
303
304
fprintf(stderr, "%s: Out of date file %s\n", progName, htfname);
305
exit(1);
306
}
307
htsize = htstat.st_size;
308
309
/*
310
* 2. Count the pages in the file.
311
*/
312
npages = 0;
313
fstart = ftell(htdbFile);
314
fend = ftell(htdbFile);
315
316
while (fgets(htdbLine, MAX_HTDB_LINE, htdbFile) != NULL) {
317
if (htdbLine[0] == '\t')
318
break;
319
if (!strncmp(htdbLine, "\\page", 5))
320
npages++;
321
fend = ftell(htdbFile);
322
}
323
324
/*
325
* 3. Find offset and size of each \page (skipping \newcommands etc.)
326
*/
327
if (npages > pgInfoC) {
328
if (pgInfoV)
329
free(pgInfoV);
330
331
pgInfoC = npages;
332
pgInfoV = (PgInfo *)
333
malloc(npages * sizeof(PgInfo));
334
335
if (!pgInfoV) {
336
fprintf(stderr, "%s: out of memory\n", progName);
337
exit(1);
338
}
339
}
340
341
fseek(htdbFile, fstart, 0);
342
343
for (i = 0; fgets(htdbLine, MAX_HTDB_LINE, htdbFile) != NULL;) {
344
if (htdbLine[0] == '\t')
345
break;
346
347
sscanf(htdbLine, "%s %s %ld %ld",
348
enttype, entname, &entoffset, &entlineno);
349
350
if (i > 0 && pgInfoV[i - 1].size == -1)
351
pgInfoV[i - 1].size = entoffset - pgInfoV[i - 1].start;
352
353
if (!strcmp(enttype, "\\page")) {
354
strncpy(pgInfoV[i].name, entname, MAX_ENTRY_NAME);
355
pgInfoV[i].start = entoffset;
356
pgInfoV[i].size = -1;
357
358
i++;
359
}
360
}
361
if (i > 0 && pgInfoV[i - 1].size == -1)
362
pgInfoV[i - 1].size = htsize - pgInfoV[i - 1].start;
363
364
if (i != npages)
365
badDB();
366
367
/*
368
* 4. Position database input to read next file-description
369
*/
370
fseek(htdbFile, fend, 0);
371
372
/*
373
* 5. Process the pages of the file.
374
*/
375
handleFilePages(htfname, npages, pgInfoV);
376
}
377
378
static void
379
handleHtdb()
380
{
381
FILE *htdbFile;
382
int c;
383
384
htdbFile = fopen(htdbFName, "r");
385
if (htdbFile == NULL)
386
badDB();
387
388
while ((c = getc(htdbFile)) != EOF) {
389
if (c != '\t')
390
badDB();
391
ungetc(c, htdbFile);
392
393
handleFile(htdbFile);
394
}
395
fclose(htdbFile);
396
}
397
398
static void
399
cmdline(int argc, char** argv)
400
{
401
progName = argv[0];
402
403
if (argc != 3) {
404
fprintf(stderr, "Usage: %s pattern htdb-file\n", progName);
405
exit(1);
406
}
407
408
pattern = argv[1];
409
htdbFName = argv[2];
410
}
411
412
413
int
414
main(int argc, char** argv)
415
{
416
using namespace OpenAxiom;
417
oa_setenv("LC_ALL", "C");
418
setlocale(LC_ALL, "");
419
cmdline(argc, argv);
420
regcomp(&reg_pattern, pattern, REG_NEWLINE);
421
handleHtdb();
422
return(0);
423
}
424
425