|
|
1.1 root 1: /*
2: * This program is in public domain; written by Dave G. Conroy.
3: * This file contains the main driving routine, and some keyboard processing
4: * code, for the MicroEMACS screen editor.
5: * Modified by W. L. Sheldon for use with the COHERENT Operating System -
6: * VT100 terminal key bindings.
7: */
8:
9: #include <stdio.h>
10: #include "ed.h"
11:
12: #if VMS
13: #include <ssdef.h>
14: #define GOOD (SS$_NORMAL)
15: #define BAD (SS$_ABORT)
16: #endif
17:
18: #ifndef GOOD
19: #define GOOD 0
20: #define BAD 1
21: #endif
22:
23: int currow; /* Working cursor row */
24: int curcol; /* Working cursor column */
25: int curgoal; /* Goal column */
26: BUFFER *curbp; /* Current buffer */
27: WINDOW *curwp; /* Current window */
28: BUFFER *bheadp; /* BUFFER listhead */
29: WINDOW *wheadp; /* WINDOW listhead */
30: BUFFER *blistp; /* Buffer list BUFFER */
31: #if LIBHELP
32: BUFFER *helpbp; /* Help buffer */
33: #endif
34: BUFFER *errbp; /* Error file BUFFER */
35: uchar pat[NPAT]; /* Pattern */
36:
37: uchar errfile[NFILEN]; /* Error file name */
38:
39: #if LIBHELP
40: uchar *helpfile=0; /* Help file name ptr. */
41: uchar *helpindex=0; /* Help index file name ptr. */
42: uchar hfname[NFILEN]; /* Help file name place */
43: uchar hiname[NFILEN]; /* Help index file name place */
44: #endif
45: extern char *strcpy(); /* copy string */
46: extern char *getenv();
47:
48: /*
49: * File-name list for command line...
50: */
51: uchar *cfiles[NCFILES]; /* Command line specified files */
52: int cfilecnt; /* File count... */
53:
54: /*
55: * Command line switch flags...
56: */
57: unsigned int runswitch;
58:
59: #if LK201
60: /*
61: * Mapping table for all of the funny keys with the numeric parameters
62: * on the LK201.
63: * Indexed by the code, which is between 0 (unused) and 34 (F20).
64: * An entry of 0 means no mapping. The map goes to command keys.
65: * If I had a "special" bit, I could use the code in the escape sequence
66: * as a key code, and return (for example) "do" as SPECIAL + 29.
67: * Then the dispatch would be done by the default keymap. This is probably a
68: * better way to go.
69: */
70: short lkmap[] = {
71: #if EXKEYS
72: 0,
73: FN18, /* 1 Find */
74: FN19, /* 2 Insert here */
75: FN1A, /* 3 Remove */
76: FN1B, /* 4 Select */
77: FN1C, /* 5 Previous screen */
78: FN1D, /* 6 Next screen */
79: 0,
80: 0,
81: 0,
82: FN17, /* 10 Compose */
83: 0,
84: FN3, /* 12 Print screen */
85: 0,
86: FN4, /* 14 F4 */
87: 0,
88: 0,
89: FN6, /* 17 F6 */
90: FN7, /* 18 F7 */
91: FN8, /* 19 F8 */
92: FN9, /* 20 F9 */
93: FNA, /* 21 F10 */
94: 0,
95: 0,
96: 0,
97: 0,
98: FNE, /* 26 F14 */
99: 0,
100: FN15, /* 28 Help */
101: FN16, /* 29 Do C-X E */
102: 0,
103: FN11, /* 31 F17 C-X P */
104: FN12, /* 32 F18 C-X N */
105: FN13, /* 33 F19 C-X Z */
106: FN14 /* 34 F20 C-X C-Z */
107: #else
108: 0,
109: OBND|CTRL|'S', /* 1 Find */
110: OBND|CTRL|'Y', /* 2 Insert here */
111: OBND|CTRL|'W', /* 3 Remove */
112: OBND|CTRL|'@', /* 4 Select */
113: OBND|META|'V', /* 5 Previous screen */
114: OBND|CTRL|'V', /* 6 Next screen */
115: 0,
116: 0,
117: 0,
118: 0, /* 10 Compose */
119: 0,
120: 0, /* 12 Print screen */
121: 0,
122: 0, /* 14 F4 */
123: 0,
124: 0,
125: 0, /* 17 F6 */
126: 0, /* 18 F7 */
127: 0, /* 19 F8 */
128: 0, /* 20 F9 */
129: 0, /* 21 F10 */
130: 0,
131: 0,
132: 0,
133: 0,
134: 0, /* 26 F14 */
135: 0,
136: 0, /* 28 Help */
137: OBND|PFX1|'E', /* 29 Do C-X E */
138: 0,
139: OBND|PFX1|'P', /* 31 F17 C-X P */
140: OBND|PFX1|'N', /* 32 F18 C-X N */
141: OBND|PFX1|'Z', /* 33 F19 C-X Z */
142: OBND|PFX1|CTRL|'Z' /* 34 F20 C-X C-Z */
143: #endif
144: };
145: #endif
146:
147: main(argc, argv)
148: uchar *argv[];
149: {
150: register int c;
151: register int f;
152: register int n;
153: uchar bname[NBUFN];
154:
155: #if MSDOS
156: setkeys();
157: #endif
158: #if IBM
159: vidnit();
160: #endif
161: for (c = 0; c < MAXREB; c++) /* nothing in the new table */
162: bind.table[c].k_synonym = bind.table[c].k_code = -1;
163: runswitch = 0; /* Initialize the switches */
164: bind.ffold = FALSE; /* initialize the fold flg */
165: bind.bracket = 1; /* initialize bracket mode */
166: bind.pfx1 = CTRL|'X'; /* initialize prefix keys */
167: bind.pfx2 = bind.pfx3 = -1;
168: bind.repeat = CTRL|'U';
169: argproc(argc, argv); /* Parse the arg list */
170: #if GEM
171: if (runswitch & CF_GRABMEM) /* Get largest chunk of */
172: grabmem(0, 0); /* memory (ST only) */
173: #endif
174: topen(); /* Force the length setup */
175: strcpy(bname, "main"); /* Work out the name of */
176: if (cfilecnt > 0) /* the default buffer. */
177: makename(bname, cfiles[0]); /* Make a buffer name */
178: edinit(bname); /* Buffers, windows. */
179: vtinit(); /* Displays. */
180: if (cfilecnt > 0) { /* If there are files */
181: update(); /* You have to update */
182: readin(cfiles[0]); /* in case "[New file]" */
183: }
184: if (cfilecnt > 1) { /* If more than one */
185: n = (term.t_nrow - cfilecnt - 1) / cfilecnt;
186: for (c = 1; c < cfilecnt ; c++) { /* For all other files... */
187: splitwind(0,0); /* Split this window... */
188: if ((f=curwp->w_ntrows-n) != 0)
189: shrinkwind(0,f); /* Even out the windows */
190: nextwind(0,0); /* Go on to the next one */
191: visitfile(cfiles[c]); /* Read in that file */
192: }
193: }
194: if ((runswitch & CF_ERROR) != 0) {
195: splitwind(0,0); /* Split this window */
196: f = curwp->w_ntrows - ERRLINES; /* Make error window small */
197: if (f > 0)
198: shrinkwind(0,f);
199: readerr();
200: nextwind();
201: mlerase();
202: update();
203: nexterr(0,1);
204: update();
205: }
206: lastflag = 0; /* Fake last flags. */
207: if (NULL != bind.macs[MAXMAC]) /* initialization macro */
208: doMac(bind.macs + MAXMAC, FALSE, 1);
209:
210: for (;;) {
211: update(); /* Fix up the screen */
212: c = getbind(0); /* Get a key */
213: if (mpresf != FALSE) { /* If a message there */
214: mlerase(); /* get rid of it... */
215: update(); /* Fix screen */
216: if (c == ' ') /* ITS EMACS does this */
217: continue; /* (eat a space) */
218: }
219: f = FALSE;
220: n = 1;
221: if (c == bind.repeat) { /* ^U, start argument */
222: int ctmp;
223:
224: f = TRUE; /* We have a count */
225: n = getnum("Arg", 4, &ctmp); /* get the count */
226: c = ctmp; /* And get the last chr */
227: }
228: if (kbdmip != NULL) { /* Save macro strokes. */
229: if (kbdmip > (kbdm + ((NKBDM - 3)/2))) {
230: ctrlg(FALSE, 0);
231: continue;
232: }
233: if (f != FALSE) {
234: *kbdmip++ = bind.repeat;
235: *kbdmip++ = n;
236: }
237: *kbdmip++ = c;
238: }
239: bracketoff();
240: execute(c, f, n); /* Do it. */
241: }
242: }
243:
244: /*
245: * Initialize all of the buffers and windows.
246: * The buffer name is passed down as an argument, because the main routine may
247: * have been told to read in a file by default, and we want the buffer name to
248: * be right.
249: */
250: edinit(bname)
251: uchar bname[];
252: {
253: register BUFFER *bp;
254: register WINDOW *wp;
255:
256: bp = bfind(bname, TRUE, 0); /* First buffer */
257: blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */
258: #if LIBHELP
259: helpbp = bfind("[Help]", TRUE, BFTEMP|BFHELP); /* Help buffer */
260: #endif
261: wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */
262: if (bp==NULL || wp==NULL || blistp==NULL)
263: abort();
264: curbp = bp; /* Make this current */
265: wheadp = wp;
266: curwp = wp;
267: wp->w_wndp = NULL; /* Initialize window */
268: wp->w_bufp = bp;
269: bp->b_nwnd = 1; /* Displayed. */
270: wp->w_linep = bp->b_linep;
271: wp->w_dotp = bp->b_linep;
272: wp->w_doto = 0;
273: wp->w_markp = NULL;
274: wp->w_marko = 0;
275: wp->w_toprow = 0;
276: wp->w_ntrows = term.t_nrow-1; /* "-1" for mode line. */
277: wp->w_force = 0;
278: wp->w_flag = WFMODE|WFHARD; /* Full. */
279: }
280:
281:
282: /*
283: * Read in a key. Do the standard keyboard preprocessing.
284: * Convert the keys to the internal character set. On the LK201, which lacks
285: * a reasonable ESC key, make the grave accent a meta key too; this is a fairly
286: * common customization around Digital. Also read and decode the arrow keys,
287: * and other special keys. This is done in Rainbow mode; does this work on all
288: * the terminals with LK201 keyboards?
289: */
290: getkey()
291: {
292: register int c;
293: #if LK201
294: register int n;
295: for (;;) {
296: if ((c = tgetc()) == AGRAVE) /* Alternate M- prefix. */
297: return (META | getCtl());
298: if (c == METACH) { /* M-, or special key. */
299: if ((c = tgetc()) == '[') { /* Arrows and extras. */
300: switch (c = tgetc()) {
301: case 'A':
302: return (OBND | CTRL | 'P');
303: case 'B':
304: return (OBND | CTRL | 'N');
305: case 'C':
306: return (OBND | CTRL | 'F');
307: case 'D':
308: return (OBND | CTRL | 'B');
309: }
310: if (c >= '0' && c <= '9') {
311: n = 0;
312: do {
313: n = 10*n + c - '0';
314: }
315: while ((c = tgetc()) >= '0' && c <= '9');
316: if (c == '~' && n <= 34 && (c = lkmap[n]))
317: return (c);
318: }
319: continue;
320: }
321: if (c == 'O') {
322: switch (tgetc()) {
323: case 'P': /* PF1 => M-X (Future) */
324: return (OBND | META | 'X');
325: case 'Q': /* PF2 => C-Q */
326: return (OBND | CTRL | 'Q');
327: case 'R': /* PF3 => C-S */
328: return (OBND | CTRL | 'S');
329: case 'S': /* PF4 => C-R */
330: return (OBND | CTRL | 'R');
331: }
332: continue;
333: }
334: return (META | toCtl(c));
335: }
336: break;
337: }
338: #else
339: #if VT100
340: for (;;) {
341: if ((c = tgetc()) == METACH) { /* Apply M- prefix */
342: if ((c = tgetc()) == '[') { /* Arrow keys. */
343: switch (tgetc()) {
344: case 'A':
345: return (OBND | CTRL | 'P');
346: case 'B':
347: return (OBND | CTRL | 'N');
348: case 'C':
349: return (OBND | CTRL | 'F');
350: case 'D':
351: return (OBND | CTRL | 'B');
352: case 'P':
353: return (OBND | CTRL | 'D'); /* DEL key */
354: case 'H':
355: return (OBND | CTRL | 'A'); /* HOME key */
356: case '1':
357: switch (tgetc()) {
358: case 'x':
359: return (OBND | META | '?'); /* F1 help C/ASM word */
360: case 'y':
361: return (OBND | PFX1 | '2'); /* Alt-F1 open 2nd window */
362: }
363: case '2':
364: switch (tgetc()) {
365: case '4':
366: if ((tgetc()) == 'H')
367: return (OBND | CTRL | 'E'); /* END key */
368: case 'x':
369: return (OBND | PFX1 | CTRL | 'V'); /* new file F2 */
370: }
371: case 'V':
372: return (OBND | META | 'V'); /* PGUP key */
373: case 'U':
374: return (OBND | CTRL | 'V'); /* PGDN key */
375: case '3':
376: switch (tgetc()) {
377: case 'x':
378: return (OBND | META | 'S'); /* F3 search forward */
379: case 'y':
380: return (OBND | META | '/'); /* ALT-F3 cont search */
381: }
382: case '4':
383: tgetc();
384: return (OBND | META | 'R'); /* F4 search backward */
385: case '5':
386: tgetc();
387: return (OBND | META | '%'); /* F5 search & replace */
388: case '6':
389: tgetc();
390: return (OBND | PFX1 | 'N'); /* F6 next window */
391: case '8':
392: tgetc();
393: return (OBND | CTRL | 'Z'); /* F8 save/exit */
394: case '0':
395: switch (tgetc()) {
396: case 'x':
397: return (OBND | PFX1 | '1'); /* F10 close other wndws */
398: case 'y':
399: return (OBND | META | 'J');
400: }
401: }
402: continue;
403: }
404: if (c == 'O') { /* function keys */
405: switch (tgetc()) {
406: case 'P': /* PF1 => M-X (Future) */
407: return (OBND | META | 'X');
408: case 'Q': /* PF2 => C-Q */
409: return (OBND | CTRL | 'Q');
410: case 'R': /* PF3 => C-S */
411: return (OBND | CTRL | 'S');
412: case 'S': /* PF4 => C-R */
413: return (OBND | CTRL | 'R');
414: }
415: continue;
416: }
417: return (META | toCtl(c));
418: }
419: break;
420: }
421: #else
422: if ((c = tgetc()) == METACH) /* Apply M- prefix */
423: return (META | getCtl());
424: #endif
425: #endif
426: if (c == 0x0D && bind.autoindent)
427: return (OBND | CTRL | 'J');
428: if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */
429: return (CTRL | '@' | c);
430: return (c);
431: }
432:
433: /*
434: * Apply control modifications to a key
435: */
436: toCtl(c)
437: register int c;
438: {
439: if (c>='a' && c<='z') /* Force to upper */
440: return (c - 0x20);
441: if (c>=0x00 && c<=0x1F) /* C0 control -> C- */
442: return (c | CTRL | '@');
443: return (c);
444: }
445:
446: getCtl()
447: {
448: return (toCtl(tgetc()));
449: }
450:
451: /*
452: * Fancy quit command, as implemented by Norm.
453: * If the current buffer has changed do a write current buffer and exit emacs,
454: * otherwise simply exit.
455: */
456: quickexit(f, n)
457: {
458: if ((curbp->b_flag&BFCHG) != 0 /* Changed. */
459: && (curbp->b_flag&(BFTEMP|BFERROR|BFNOWRT)) == 0)
460: /* Real and not R/O... */
461: filesave(f, n);
462: quit(f, n); /* conditionally quit */
463: }
464:
465: /*
466: * Quit command. If an argument, always quit. Otherwise confirm
467: * if a buffer has been changed and not written out.
468: * Normally bound to "C-X C-C".
469: */
470: quit(f, n)
471: {
472: register int s = FALSE;
473:
474: if (f != FALSE /* Argument forces it. */
475: || anycb() == FALSE /* All buffers clean. */
476: || (s=mlyesno("Quit")) == TRUE) { /* User says it's OK. */
477: vttidy();
478: #if MSDOS
479: resetkeys();
480: #endif
481: if (f != FALSE || s != FALSE)
482: exit(BAD);
483: else
484: exit(GOOD);
485: }
486: #if MSDOS
487: setkeys();
488: #endif
489: return (s);
490: }
491:
492: /*
493: * Get binding char. Turn prefix chars into or'ed bits.
494: */
495: getbind(bound)
496: register int bound;
497: {
498: register int c;
499:
500: if (((c = getkey()) == bind.pfx1) && !(bound & PFX1))
501: return (PFX1 | toCtl(getbind(bound | PFX1)));
502: if ((c == bind.pfx2) && !(bound & PFX2))
503: return (PFX2 | toCtl(getbind(bound | PFX2)));
504: if ((c == bind.pfx3) && !(bound & PFX3))
505: return (PFX3 | toCtl(getbind(bound | PFX3)));
506: return (c);
507: }
508:
509: /*
510: * Abort.
511: * Beep the beeper.
512: * Kill off any keyboard macro,
513: * etc., that is in progress.
514: * Sometimes called as a routine,
515: * to do general aborting of
516: * stuff.
517: */
518: ctrlg(f, n)
519: {
520: tbeep();
521: if (kbdmip != NULL) {
522: if (NULL != kbdm) {
523: free(kbdm);
524: kbdm = NULL;
525: }
526: kbdmip = NULL;
527: }
528: return (ABORT);
529: }
530:
531: #if MSDOS
532: setkeys() /* redefine cursor keys */
533: /* so that they make */
534: /* sense to microEMACS */
535: /* as described in IBM */
536: /* DOS tech. reference */
537: /* manual */
538: {
539: #if !IBM
540: static uchar *ctlseq[] = {
541: "\033[0;72;16p", /* up = <ctrl-p> */
542: "\033[0;77;6p", /* right = <ctrl-f> */
543: "\033[0;75;2p", /* left = <ctrl-b> */
544: "\033[0;80;14p", /* down = <ctrl-n> */
545: "\033[0;81;22p", /* pg dn = <ctrl-v> */
546: "\033[0;73;27;86p", /* pg up = <esc>V */
547: "\033[0;71;27;60p", /* home = <esc>< */
548: "\033[0;79;27;62p", /* end = <esc>> */
549: "\033[0;83;127p", /* del = del */
550: "\033[0;3;27;46p", /* <ctrl-@> = <exc>. */
551: NULL
552: };
553: register uchar **ctlp;
554:
555: for (ctlp = ctlseq; NULL != *ctlp; ctlp++)
556: mlwrite(*ctlp);
557: #endif
558: }
559:
560:
561:
562: resetkeys() /* redefine cursor keys */
563: /* to default values */
564: {
565: #if !IBM
566: static uchar *ctlseq[] = {
567: "\033[0;72;0;72p",
568: "\033[0;77;0;77p",
569: "\033[0;75;0;75p",
570: "\033[0;80;0;80p",
571: "\033[0;81;0;81p",
572: "\033[0;73;0;73p",
573: "\033[0;71;0;71p",
574: "\033[0;79;0;79p",
575: "\033[0;83;0;83p",
576: "\033[0;3;0;3p",
577: NULL
578: };
579: register uchar **ctlp;
580:
581: for (ctlp = ctlseq; NULL != *ctlp; ctlp++)
582: mlwrite(*ctlp);
583: #endif
584: }
585: #endif
586:
587: argproc(argc, argv)
588: int argc;
589: uchar **argv;
590: {
591: int i;
592: uchar *flexn;
593: extern uchar *flexName();
594: uchar *ptr;
595:
596: if (!bind.tabsiz &&
597: (NULL == (ptr = getenv("TABSIZ")) ||
598: !(bind.tabsiz = atoi(ptr))))
599: bind.tabsiz = 8;
600: cfilecnt = 0;
601: flexn = NULL;
602: for (i = 1; i < argc; i++) {
603: ptr = argv[i]; /* Get this argument... */
604: if (*ptr == '-') { /* Is this a switch? */
605: switch (ptr[1]) {
606: case 'd':
607: runswitch |= CF_DEBUG;
608: break;
609: case 'e':
610: runswitch |= CF_ERROR;
611: if (ptr[2] == 0) {
612: if (++i == argc) {
613: runswitch &= ~CF_ERROR;
614: continue;
615: }
616: strcpy(errfile, argv[i]);
617: }
618: else {
619: strcpy(errfile, &ptr[2]);
620: }
621: break;
622: case 'f':
623: if (ptr[2] == 0) {
624: if (++i == argc)
625: continue;
626: flexn = argv[i];
627: }
628: else
629: flexn = ptr + 1;
630: break;
631: #if LIBHELP
632: case 'h': /* Alternate help */
633: if (ptr[2] == 0) {
634: if (++i == argc) {
635: continue;
636: }
637: strcpy(hfname, argv[i]);
638: }
639: else {
640: strcpy(hfname, &ptr[2]);
641: }
642: strcpy(hiname, hfname);
643: #if GEM || MSDOS
644: strcat(hfname, ".hlp");
645: #endif
646: strcat(hiname, ".idx");
647: helpfile = hfname;
648: helpindex = hiname;
649: break;
650: #endif
651: case 'w':
652: runswitch |= CF_WARN;
653: break;
654: #if NATIVE && GEM
655: case 'l': /* long screen */
656: runswitch |= CF_LONGSCR;
657: break;
658: case 't': /* very long screen */
659: runswitch |= CF_VLONG;
660: break;
661: #endif
662: #if GEM
663: case 'x': /* grab all memory */
664: runswitch |= CF_GRABMEM;
665: break;
666: #endif
667: default:
668: break;
669: }
670: /* Process this switch */
671: }
672: else { /* Otherwise... */
673: if (cfilecnt >= NCFILES)
674: continue;
675: cfiles[cfilecnt++] = ptr; /* This is a file. */
676: #if GEM
677: fixname(cfiles[cfilecnt-1]);
678: #endif
679: }
680: }
681: if (NULL == flexn)
682: loadBup(flexName(), TRUE);
683: else
684: loadBup(flexn, ABORT);
685: }
686:
687: #if EXKEYS
688: /*
689: * Do nothing. ("Dead")
690: */
691: ignore()
692: {
693: return TRUE;
694: }
695: #endif
696:
697: /*
698: * Get a numeric argument...
699: */
700: getnum(prompt, n, lastc)
701: register uchar *prompt;
702: register int n;
703: register int *lastc;
704: {
705: register int mflag = 0;
706: register int c;
707:
708: mflag = 0; /* that can be discarded. */
709: mlwrite("%s: %d", prompt, n);
710: while ((c = getbind(0)) >='0' && c<='9'
711: || c==bind.repeat || c=='-'){
712: if (c == bind.repeat)
713: n = n*4;
714: /*
715: * If dash, and start of argument string, set arg.
716: * to -1. Otherwise, insert it.
717: */
718: else if (c == '-') {
719: if (mflag)
720: break;
721: n = 0;
722: mflag = -1;
723: }
724: /*
725: * If first digit entered, replace previous argument
726: * with digit and set sign. Otherwise, append to arg.
727: */
728: else {
729: if (!mflag) {
730: n = 0;
731: mflag = 1;
732: }
733: n = 10*n + c - '0';
734: }
735: mlwrite("%s: %d", prompt, (mflag >=0) ? n : (n ? -n : -1));
736: }
737: *lastc = c; /* Return the terminal char. */
738: /*
739: * Make arguments preceded by a minus sign negative and change
740: * the special argument "^U -" to an effective "^U -1".
741: */
742: if (mflag == -1) {
743: if (n == 0)
744: n++;
745: n = -n;
746: }
747: return n;
748: }
749:
750: #if GEM
751: /*
752: * The following routine gets around a problem with GEMDOS Malloc(),
753: * it forces a single, very large Malloc() so very large files can
754: * be read.
755: * It is available only on the Atari ST, and is bound to M-+
756: * it can also be specified using the -x switch
757: */
758: #include <osbind.h>
759:
760: grabmem(f, n)
761: int f, n;
762: {
763: extern char *lmalloc();
764: register char *p = NULL;
765: register long t;
766:
767: t = Malloc(-1L); /* How big is free memory? */
768: while (p == NULL) { /* Until we have a block */
769: t -= 4096L; /* shrink the block */
770: if (t < 2048) { /* if too small, tell user */
771: mlwrite( "[Cannot allocate memory]" );
772: return 1; /* and fail */
773: }
774: p = lmalloc(t); /* Try to get this chunk */
775: } /* loop until success or fail */
776: free(p); /* return chunk to arena */
777: mlwrite( "[Allocated %ld bytes]", t ); /* tell user how much */
778: return 0; /* and return success */
779: }
780: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.