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-2011 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
* Word completion.
37
*
38
*
39
* Word completion is driven from a list of completion tables. Each table
40
* contains a list of words.
41
*
42
*/
43
44
#include "openaxiom-c-macros.h"
45
46
#include <stdio.h>
47
#include <stdlib.h>
48
#include <unistd.h>
49
#include <string.h>
50
#include <fcntl.h>
51
#include <time.h>
52
#include <ctype.h>
53
#include <sys/types.h>
54
#include <sys/stat.h>
55
56
/* #define PINFO *//* A flag to suppress printing of the file info */
57
58
#define WCT /* A flag needed because ctype.h stole some
59
* of my constants */
60
#include "edible.h"
61
62
#define MAX_PREFIX 1024
63
#define strneql(a,b,n) (*(a) == *(b) && !strncmp((a),(b),(n)))
64
#define Delimiter(c) (! isalnum(c) && c != '%' && c != '!' && c != '?' && c != '_')
65
66
67
#include "wct.h"
68
#include "prt.h"
69
#include "edin.h"
70
71
72
73
static Wct *pwct = 0;
74
static Wix *pwix;
75
static Wix curr_wix;
76
static char curr_prefix[MAX_PREFIX];
77
static Wct *pHeadwct;
78
79
time_t
80
ftime(char *path)
81
{
82
int rc;
83
struct stat stbuf;
84
85
rc = stat(path, &stbuf);
86
if (rc == -1)
87
fatal("Cannot deterimine status of %s.", path);
88
89
return stbuf.st_mtime;
90
}
91
92
off_t
93
fsize(char *path)
94
{
95
int rc;
96
struct stat stbuf;
97
98
rc = stat(path, &stbuf);
99
if (rc == -1)
100
fatal("Cannot deterimine status of %s.", path);
101
102
return stbuf.st_size;
103
}
104
105
106
/*
107
* Scan a word completion table for a particular word.
108
*/
109
110
111
Wix *
112
scanWct(Wct *pwct, char *prefix)
113
{
114
long fmod;
115
int preflen, i, wc;
116
char **wv;
117
118
preflen = strlen(prefix);
119
strncpy(curr_prefix, prefix, MAX_PREFIX);
120
121
pHeadwct = pwct;
122
curr_wix.pwct = 0;
123
curr_wix.word = 0;
124
125
for (; pwct; pwct = pwct->next) {
126
curr_wix.pwct = pwct;
127
128
129
130
fmod = ftime(pwct->fname);
131
if (fmod > pwct->ftime)
132
reintern1Wct(pwct);
133
134
wv = pwct->wordv;
135
wc = pwct->wordc;
136
for (i = 0; i < wc; i++) {
137
curr_wix.word = i;
138
if (strneql(wv[i], prefix, preflen))
139
return &curr_wix;
140
}
141
}
142
return 0;
143
}
144
145
Wix *
146
rescanWct(void)
147
{
148
Wct *pwct, *start_pwct;
149
int preflen, start_word, i, wc;
150
char **wv, *prefix;
151
152
start_pwct = curr_wix.pwct;
153
start_word = curr_wix.word;
154
155
if (!start_pwct) return(0);
156
prefix = curr_prefix;
157
preflen = strlen(prefix);
158
159
/*
160
* Finish the current structure.
161
*/
162
163
pwct = start_pwct;
164
165
curr_wix.pwct = pwct;
166
wv = pwct->wordv;
167
wc = pwct->wordc;
168
for (i = start_word + 1; i < wc; i++) {
169
curr_wix.word = i;
170
if (strneql(wv[i], prefix, preflen))
171
return &curr_wix;
172
}
173
174
/*
175
* Finish to the end of the list, doing whole structures.
176
*/
177
for (pwct = pwct->next; pwct; pwct = pwct->next) {
178
curr_wix.pwct = pwct;
179
180
wv = pwct->wordv;
181
wc = pwct->wordc;
182
for (i = 0; i < wc; i++) {
183
curr_wix.word = i;
184
if (strneql(wv[i], prefix, preflen))
185
return &curr_wix;
186
}
187
}
188
189
/*
190
* Restart at beginning, doing whole structures.
191
*/
192
for (pwct = pHeadwct; pwct != start_pwct; pwct = pwct->next) {
193
curr_wix.pwct = pwct;
194
195
wv = pwct->wordv;
196
wc = pwct->wordc;
197
for (i = 0; i < wc; i++) {
198
curr_wix.word = i;
199
if (strneql(wv[i], prefix, preflen))
200
return &curr_wix;
201
}
202
}
203
204
/*
205
* Do beginning half of the start structure.
206
*/
207
curr_wix.pwct = pwct;
208
wv = pwct->wordv;
209
wc = pwct->wordc;
210
for (i = 0; i <= start_word; i++) {
211
curr_wix.word = i;
212
if (strneql(wv[i], prefix, preflen))
213
return &curr_wix;
214
}
215
216
/* Not found? */
217
return 0;
218
}
219
220
/*
221
* Summarize a table.
222
*/
223
void
224
skimWct(Wct *pwct)
225
{
226
while (pwct) {
227
#ifdef PINFO
228
skim1Wct(pwct);
229
#endif
230
pwct = pwct->next;
231
}
232
}
233
234
void
235
skim1Wct(Wct *pwct)
236
{
237
#define NHEAD 13
238
#define NTAIL 7
239
240
int cc;
241
242
printf("%-10s", pwct->fname);
243
printTime((long *)&(pwct->ftime));
244
cc = skimString(pwct->fimage, pwct->fsize, NHEAD, NTAIL);
245
printf("%s", " " + (cc - (NHEAD + NTAIL)));
246
printf(" [%d w, %ld c]", pwct->wordc, (long)(pwct->fsize));
247
printf("\n");
248
249
#ifdef SHOW_WORDS
250
{
251
int i;
252
char **wv;
253
254
for (i = 1, wv = pwct->wordv; *wv; i++, wv++) {
255
printf("%5d: %s\n", i, *wv);
256
}
257
}
258
#endif
259
}
260
261
void
262
printTime(long *clock)
263
{
264
struct tm *tm;
265
266
tm = localtime((time_t *)clock);
267
printf("%.2d/%.2d/%.2d %.2d:%.2d:%.2d ",
268
tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
269
tm->tm_hour, tm->tm_min, tm->tm_sec);
270
}
271
272
int
273
skimString(char *s, int slen,int nhead,int ntail)
274
{
275
int spos, tlen, i, cc;
276
277
cc = printf("\"");
278
for (spos = 0; spos < slen && cc <= nhead; spos++)
279
cc += prChar(s[spos]);
280
281
/* Assume same tail has the same multi-character format ratio. */
282
tlen = ntail * ((1.0 * spos) / nhead);
283
284
if (spos + tlen >= slen)
285
for (; spos < slen; spos++)
286
cc += prChar(s[spos]);
287
else {
288
cc += printf("\"...\"");
289
for (i = slen - tlen; i < slen; i++)
290
cc += prChar(s[i]);
291
}
292
cc += printf("\"");
293
return cc;
294
}
295
296
int
297
prChar(int c)
298
{
299
if (c == '\n')
300
return printf("\\n");
301
if (c == '\t')
302
return printf("\\t");
303
if (c == '\b')
304
return printf("\\b");
305
if (c == '"')
306
return printf("\\\"");
307
if (iscntrl(c))
308
return printf("^%c", (c + 0100) % 0200);
309
if (isascii(c))
310
return printf("%c", c);
311
312
return printf("\\%d", c);
313
}
314
315
Wct *
316
reread1Wct(Wct *pwct)
317
{
318
int fd, rc;
319
320
/* Check information about the file. */
321
pwct->fsize = fsize(pwct->fname);
322
pwct->ftime = ftime(pwct->fname);
323
324
/* Allocate space for file image */
325
if (pwct->fimage)
326
free(pwct->fimage);
327
pwct->fimage = (char *) malloc(pwct->fsize + 1);
328
if (pwct->fimage == 0)
329
sfatal("Cannot allocate new table.");
330
pwct->fimage[pwct->fsize] = 0;
331
332
/* Read file into buffer. */
333
fd = open(pwct->fname, O_RDONLY);
334
if (fd == -1)
335
fatal("Cannot read file %s.", pwct->fname);
336
rc = read(fd, pwct->fimage, pwct->fsize);
337
if (rc != pwct->fsize)
338
fatal("Did not read all of file %s.", pwct->fname);
339
340
return pwct;
341
}
342
343
Wct *
344
read1Wct(char *fname)
345
{
346
Wct *pwct;
347
348
/* Allocate a new link for this file. */
349
pwct = (Wct *) malloc(sizeof(Wct));
350
if (pwct == 0)
351
sfatal("Cannot allocate new table.");
352
353
pwct->fname = fname;
354
pwct->wordc = 0;
355
pwct->wordv = 0;
356
pwct->fimage = 0;
357
pwct->next = 0;
358
359
return reread1Wct(pwct);
360
}
361
362
Wct *
363
nconcWct(Wct *pwct,Wct * qwct)
364
{
365
Wct *p0 = pwct;
366
367
if (!p0)
368
return qwct;
369
370
while (pwct->next)
371
pwct = pwct->next;
372
pwct->next = qwct;
373
374
return p0;
375
}
376
377
void
378
sortWct(Wct *pwct)
379
{
380
while (pwct) {
381
sort1Wct(pwct);
382
pwct = pwct->next;
383
}
384
}
385
386
void
387
sort1Wct(Wct *pwct)
388
{
389
qsort((char *) pwct->wordv, pwct->wordc,
390
sizeof(*(pwct->wordv)), mystrcmp);
391
}
392
393
int
394
mystrcmp(const void *s1,const void * s2)
395
{
396
return strcmp(*(char **)s1, *(char **)s2);
397
}
398
399
/*
400
* Break wct struct into words.
401
*/
402
403
void
404
burstWct(Wct *pwct)
405
{
406
while (pwct) {
407
burst1Wct(pwct);
408
pwct = pwct->next;
409
}
410
}
411
412
void
413
burst1Wct(Wct *pwct)
414
{
415
char *s, **wv;
416
int i, j, inword = 0;
417
418
419
for (s = pwct->fimage, i = 0; i < pwct->fsize; s++, i++) {
420
if (isspace(*s) || iscntrl(*s)) {
421
*s = 0;
422
inword = 0;
423
}
424
else if (!inword) {
425
inword = 1;
426
pwct->wordc++;
427
}
428
}
429
430
if (pwct->wordv)
431
free(pwct->wordv);
432
pwct->wordv = (char **) calloc(pwct->wordc + 1, sizeof(char *));
433
if (!pwct->wordv)
434
fatal("Could not make word list for %s.", pwct->fname);
435
436
s = pwct->fimage;
437
i = 0;
438
for (wv = pwct->wordv, j = 0; j < pwct->wordc; wv++, j++) {
439
while (i < pwct->fsize && !s[i])
440
i++;
441
*wv = s + i;
442
while (i < pwct->fsize && s[i])
443
i++;
444
}
445
*wv = 0;
446
}
447
448
Wct *
449
intern1Wct(char *fname)
450
{
451
Wct *pwct;
452
453
pwct = read1Wct(fname);
454
burst1Wct(pwct);
455
return pwct;
456
}
457
458
void
459
reintern1Wct(Wct *pwct)
460
{
461
reread1Wct(pwct);
462
burst1Wct(pwct);
463
}
464
465
void
466
sfatal(const char *s)
467
{
468
fatal("%s", s);
469
}
470
471
void
472
fatal(const char* fmt, const char* s)
473
{
474
static char fbuf[256];
475
476
sprintf(fbuf, fmt, s);
477
478
perror(fbuf);
479
exit(1);
480
}
481
482
483
484
/* load up the wct database */
485
void
486
load_wct_file(char *fname)
487
{
488
pwct = nconcWct(intern1Wct(fname), pwct);
489
}
490
491
void
492
skim_wct(void)
493
{
494
skimWct(pwct);
495
}
496
497
/*
498
* This routine is called when a tab is hit. It simply takes the current
499
* buffer and tries to find a completion of the last word on the line in the
500
* data base.
501
*/
502
503
504
void
505
rescan_wct(void)
506
{
507
int b = curr_pntr - 1;
508
int old_len;
509
int new_len;
510
int diff;
511
int i;
512
int ncs = 0;
513
514
/*
515
* first thing I should do is find my way back to the beginning of the
516
* word
517
*/
518
while (b && !Delimiter(buff[b]))
519
b--;
520
if (Delimiter(buff[b]))
521
b++;
522
523
old_len = curr_pntr - b;
524
525
pwix = rescanWct();
526
527
if (!pwix) {
528
putchar(_BELL);
529
fflush(stdout);
530
}
531
else {
532
Wct *pwct = pwix->pwct; /* start replacing it */
533
534
new_len = strlen(pwct->wordv[pwix->word]);
535
if (new_len > old_len) {
536
537
/*
538
* I have to just slide the characters forward a bit, stuff in
539
* the new characters, and then adjust curr_pntr
540
*/
541
diff = new_len - old_len;
542
if (curr_pntr != buff_pntr) {
543
forwardcopy(&buff[curr_pntr + diff],
544
&buff[curr_pntr],
545
buff_pntr - curr_pntr);
546
forwardflag_cpy(&buff_flag[curr_pntr + diff],
547
&buff_flag[curr_pntr],
548
buff_pntr - curr_pntr);
549
}
550
buff_pntr += diff;
551
ncs = curr_pntr + diff;
552
553
/* Now insert the new word */
554
for (i = 0; i < new_len; i++)
555
buff[b + i] = (pwct->wordv[pwix->word])[i];
556
557
/* move cursor to the beginning of the word */
558
for (; curr_pntr != b; curr_pntr--)
559
putchar(_BKSPC);
560
561
/** now print the characters on the rest of the line **/
562
printbuff(curr_pntr, buff_pntr - curr_pntr);
563
564
/* now move bcak the number of characters I want to */
565
for (i = buff_pntr; i != ncs; i--)
566
putchar(_BKSPC);
567
568
fflush(stdout);
569
570
curr_pntr = ncs;
571
}
572
else if (new_len < old_len) {
573
/* this time I simply copy backwards and do the substituting */
574
diff = old_len - new_len;
575
strncpy(&buff[curr_pntr - diff],
576
&buff[curr_pntr],
577
buff_pntr - curr_pntr);
578
flagncpy(&buff_flag[curr_pntr - diff],
579
&buff_flag[curr_pntr],
580
buff_pntr - curr_pntr);
581
buff_pntr -= diff;
582
ncs = curr_pntr - diff;
583
584
/* Now insert the new word */
585
for (i = 0; i < new_len; i++)
586
buff[b + i] = (pwct->wordv[pwix->word])[i];
587
588
/* move cursor to the beginning of the word */
589
for (; curr_pntr != b; curr_pntr--)
590
putchar(_BKSPC);
591
592
/** now print the characters on the rest of the line **/
593
printbuff(b, buff_pntr - b);
594
595
/* now blank out the characters out on the end of this line */
596
for (i = 0; i < diff; i++)
597
myputchar(' ');
598
599
/* now move back the number of characters I want to */
600
for (i = buff_pntr + diff; i != ncs; i--)
601
putchar(_BKSPC);
602
603
fflush(stdout);
604
605
curr_pntr = ncs;
606
}
607
else {
608
diff = 0;
609
ncs = curr_pntr;
610
/* Now insert the new word */
611
for (i = 0; i < new_len; i++)
612
buff[b + i] = (pwct->wordv[pwix->word])[i];
613
614
/* move cursor to the beginning of the word */
615
for (; curr_pntr != b; curr_pntr--)
616
putchar(_BKSPC);
617
618
/** now print the characters on the rest of the line **/
619
printbuff(curr_pntr, buff_pntr - curr_pntr);
620
621
/* now move back the number of characters I want to */
622
for (i = buff_pntr; i != ncs; i--)
623
putchar(_BKSPC);
624
625
fflush(stdout);
626
627
curr_pntr = ncs;
628
}
629
}
630
}
631
632
void
633
find_wct(void)
634
{
635
636
char search_buff[100];
637
char *filler = search_buff;
638
int b = curr_pntr - 1;
639
int e = curr_pntr;
640
int ne = 0;
641
int st;
642
Wix *pwix;
643
int curr_len;
644
int new_len;
645
int diff;
646
int i;
647
648
/*
649
* First thing I do is try and construct the string to be searched for.
650
* Basically I just start from the curr_pntr and search backward until I
651
* find a blank. Once I find a blank I copy forward until I get back to
652
* curr_pntr;
653
*/
654
if (!curr_pntr) {
655
putchar(_BELL);
656
return;
657
}
658
/* then get back to the first blank or back to the beginning */
659
while (b && !Delimiter(buff[b]))
660
b--;
661
if (Delimiter(buff[b]))
662
b++;
663
664
/* At the same time, let me find the end of the word */
665
while (e < buff_pntr && !Delimiter(buff[e])) {
666
e++;
667
ne++;
668
}
669
670
st = b;
671
curr_len = e - b;
672
673
/* now simply copy the text forward */
674
while (b < curr_pntr)
675
*filler++ = buff[b++];
676
677
*filler = '\0';
678
679
pwix = scanWct(pwct, search_buff);
680
681
/*
682
* else pwix = rescanWct();
683
*/
684
685
if (!pwix) {
686
putchar(_BELL);
687
fflush(stdout);
688
}
689
else {
690
Wct *pwct = pwix->pwct;
691
692
/*
693
* printf("Found %s in file %s\n", pwct->wordv[pwix->word],
694
* pwct->fname);
695
*/
696
/* copy them buffer into where it should be */
697
new_len = strlen(pwct->wordv[pwix->word]);
698
diff = new_len - curr_len;
699
if (curr_pntr != buff_pntr) {
700
forwardcopy(&buff[curr_pntr + diff],
701
&buff[curr_pntr],
702
buff_pntr - curr_pntr);
703
forwardflag_cpy(&buff_flag[curr_pntr + diff],
704
&buff_flag[curr_pntr],
705
buff_pntr - curr_pntr);
706
}
707
buff_pntr += diff;
708
709
710
/* Now insert the new characters */
711
for (i = new_len - diff; i < new_len; i++)
712
buff[st + i] = (pwct->wordv[pwix->word])[i];
713
714
/* Now move the cursor forward to the end of the word */
715
for (i = 0; i < diff; i++)
716
putchar(buff[curr_pntr++]);
717
718
/** now print the characters on the rest of the line **/
719
printbuff(curr_pntr, buff_pntr - curr_pntr);
720
721
/* now move bcak the number of characters I want to */
722
for (i = buff_pntr; i != e + diff; i--)
723
putchar(_BKSPC);
724
725
fflush(stdout);
726
727
curr_pntr = diff + e;
728
729
}
730
731
732
}
733
734