|
|
1.1 root 1: /* Copyright Bell Telephone Laboratories Whippany, N.J.
2:
3: * ***********************************
4: * ***********************************
5: * ***** BITE INPUT TEXT EDITOR ******
6: * *** R. B. Drake WH 8C-005 X4163 ***
7: * **** Fri Aug 24 15:21:32 1979 *****
8: * ***********************************
9: * ***********************************
10: * This routine handles all text input to bite. Text may originate from
11: * a tty or from a UNIX file or data placed in a string array. Certain
12: * syntax error messages are issued and all housekeeping having to do
13: * with line numbers and the page index is handled here.
14:
15: */
16: /* "@(#) bed.c: V 1.3 11/12/81" */
17:
18: #include "bas.h"
19: char *linptr; /* ALWAYS points to the next available
20: byte in the program txtbuf */
21: char *endob = txtbuf + (NMPAG * PGSIZ);
22: char _string[LINMAX];
23: union bascmd local;
24: union bascmd inst;
25: char linbuf[LINMAX];
26: char ascno[NOMAX],ascop[OPMAX];
27: struct pages index[NMPAG+1];
28: int pg;
29: static int size;
30: char *curptr; /* fetch sets this to point to the beginning of the
31: current line. Other routines may change it */
32: char *lbdptr; /* fetch sets this to point to the beginning
33: of the next sequential line in the txtbuf */
34: extern int singflg;
35: extern int tv;
36: /* This table is used to encode and decode certain key-worde for
37: storage compression and for ease of recognition by the execution
38: software */
39: char *keyword[] =
40: {
41: "goto", /* 1 */
42: "go to", /* 2 */
43: "then", /* 3 */
44: "to", /* 4 */
45: "step", /* 5 */
46: "<>", /* 6 */
47: "<=", /* 7 */
48: "=<", /* 10 */
49: "<", /* 11 */
50: ">=", /* 12 */
51: "=>", /* 13 */
52: ">", /* 14 */
53: "=", /* 15 */
54: "gosub", /* 16 */
55: "more", /* 17 */
56: 0 };
57: extern int rem;
58: extern int _sub;
59: extern int tel;
60: extern int stpflg;
61: extern int autflg,aut,inc;
62: bed(fp)
63: FILE *fp;
64: {
65: register char *to,*from;
66: int i,j,k,nlflg,quoflg,parflg,bflg;
67: int erflg;
68: char c,*strptr;
69: char *pt,*save;
70: char *isthere();
71:
72: /* zero the working txtbufs */
73: strptr=_string;
74: for(i=0;i<NOMAX;ascno[i++]=0);
75: for(i=0;i<OPMAX;ascop[i++]=0);
76: for(i=0;i<LINMAX;linbuf[i++]=0);
77: local.thing.opcode.lobyte=local.thing.opcode.hibyte='\0';
78: local.thing.linno=nlflg=stpflg=0;
79: expr = linbuf;
80: if(autflg != 0) /* if auto line numbering in affect */
81: {
82: aut += inc;
83: sprintf(ascno,"%d",aut);
84: }
85: /* print the prompt character */
86: if(fp != 0)
87: if(isatty(fileno(fp)))
88: printf("*%s",ascno);
89: if(fp != 0)
90: if(fgets(_string,LINMAX,fp) == 0) return(-1); /* EOF */
91: /* get a line of input from the user and store it in compressed
92: * source form unless the line number is zero in which case
93: * execute the instruction immediately
94: */
95: /* get the line number if any */
96: while(*strptr == ' ' || *strptr == ' ')
97: strptr++; /* ignore leading white space */
98: for(i=0,k=0;num((c= *strptr++)) && i < (NOMAX-1);i++)
99: {
100: ascno[i]=c;
101: aut = atoi(ascno);
102: }
103: if(ascno[0] != '\0')
104: if((local.thing.linno = aut) == 0)
105: {
106: error(0,0);
107: return(0);
108: }
109: if(c== '\n')
110: {
111: if(local.thing.linno == 0 || autflg)
112: {
113: if(fetch(-1,&lbdptr) != 0)
114: {
115: if(fetch(0,&lbdptr) != 0)
116: {
117: error(0,1);
118: return(0);
119: }
120: }
121: prin();
122: if(autflg) aut -= inc;
123: return(0);
124: }
125: /*a line number was entered
126: * but nothing followed which implies
127: *delete
128: */
129: delete();
130: return(0);
131: }
132: /* if no blank was used as a delimiter, then insure
133: * that we don't lose the first character of the opcode.lobyte
134: */
135: if( c == '.') /* if auto line num to be tuned off */
136: {
137: autflg=0;
138: aut -= inc;
139: return(0);
140: }
141: if(c== '\t')
142: {
143: local.thing.opcode.hibyte = '\201';
144: while(*strptr == '\t')
145: {
146: local.thing.opcode.hibyte = (local.thing.opcode.hibyte&0377) + 1;
147: strptr++;
148: }
149: }
150: if( c != ' ' && c != '\t')
151: {
152: ascop[0] = c;
153: k=1;
154: }
155: /* get the operation statement */
156: bflg=0;
157: for(j=0,i=k;(c= *strptr);i++)
158: {
159: if((c== ' ') && (strcmp("go",ascop) != 0))
160: {
161: bflg=1;
162: while((c= *strptr) == ' ' || c== '\014')
163: strptr++;
164: }
165: /* if an "=" is present here then the
166: *opcode.lobyte is "let" by default */
167: if(c== '=' || (c== '(' && bflg != 1))
168: {
169: ascop[i]=c;
170: strcpy(linbuf,ascop);
171: strcpy(ascop,"\010");
172: j=i+1;
173: strptr++;
174: break;
175: }
176: /* If a new line is present here then
177: * we have an operation with
178: * no following expression
179: */
180: if(c== '\n')
181: {
182: nlflg=1;
183: ascop[i]='\0';
184: break;
185: }
186: if( i< (OPMAX -1))
187: {
188: if( bflg == 1) break;
189: ascop[i]=c;
190: }
191: strptr++;
192: }
193: if(ascop[0] !=0)
194: {
195: int xxx = encode(ascop);
196:
197: local.thing.opcode.lobyte = xxx;
198: if(xxx == -1)
199: {
200: error(local.thing.linno,1);
201: local.thing.opcode.lobyte=tel;
202: pt = strcat(linbuf,ascop);
203: pt = carcat(linbuf,' ');
204: erflg=1;
205: j = pt - linbuf;
206: }
207: else erflg=0;
208: }
209: if(!nlflg)
210: {
211: /* put any expression in "linbuf" */
212: for(i=j;(c= *strptr++) != '\n';i++)
213: {
214: if(i < (LINMAX -1))
215: linbuf[i]=c;
216: }
217: /* encode keywords in the expression field */
218: while(1)
219: {
220: if(!nocode(local.thing.opcode.lobyte) && erflg == 0)
221: {
222: /* first strip any blanks and control characters
223: * out of the expression unless they are quoted */
224: quoflg = 1;
225: parflg= 0;
226: for(i=0,j=0;linbuf[i] != '\0';i++)
227: if(linbuf[i] > '\040' || quoflg== -1)
228: {
229: linbuf[j++]=linbuf[i];
230: switch (linbuf[i])
231: {
232: case '"' : quoflg *= -1;
233: break;
234: case '(' : parflg += 1;
235: break;
236: case ')' : parflg -= 1;
237: break;
238: }
239: }
240: linbuf[j]='\0';
241: if(quoflg == -1)
242: {
243: error(local.thing.linno,11);
244: }
245: if(parflg != 0)
246: {
247: error(local.thing.linno,16);
248: }
249: for(i=0;keyword[i] != 0;i++)
250: while((pt=isthere(keyword[i],linbuf,1)) != 0)
251: {
252: *pt++='\001'+i;
253: shrink(pt);
254: }
255: }
256: break;
257: }
258: }
259: /* If the line number is zero then we have
260: * a command for immediate execution
261: */
262: if( k != 0)
263: {
264: inst.thing.linno = 0;
265: expr=linbuf;
266: if(local.thing.opcode.lobyte == tv)
267: list(1);
268: else
269: {
270: bascall(local.thing.opcode.lobyte);
271: if(autflg)
272: aut -= inc;
273: }
274: return(0);
275: }
276: /* if a ligitimate line number has been entered
277: *put it in the program txtbuf
278: */
279: if(singflg != 0) /* don't permit txtbuf editing in single step */
280: {
281: error(0,12);
282: return(0); /* not fatal */
283: }
284: if(fetch(local.thing.linno,&lbdptr) == -1) inst.thing.linno = 0;
285: save=curptr;
286: /* if local.thing.linno is greater than inst.thing.linno (returned by fetch)
287: * then fetch has returned the last line of the program
288: * and the action is to add the new line to the end of the
289: * program */
290: if(local.thing.linno > inst.thing.linno)
291: {
292: pg=(linptr-txtbuf)/PGSIZ; /* calculate page number*/
293: if(index[pg].maxlin == 0)
294: {
295: index[pg].maxlin = local.thing.linno; /*first line*/
296: index[pg].begin=linptr;
297: }
298: if(local.thing.linno > index[pg].maxlin)
299: index[pg].maxlin=local.thing.linno;
300: for(i=0;i<4;i++)
301: *linptr++=local.byte[i];
302: expr = linptr;
303: for(i=0;linbuf[i] != 0;i++)
304: *linptr++=linbuf[i];
305: *linptr++='\0'; /* end the expression string */
306: linptr[0]='\0'; /* make it an eof mark */
307: linptr[1]= '\0';
308: }
309: /* if local.thing.linno is less than inst.thing.linno, then the new
310: * line must be inserted into the program txtbuf. In order
311: * to do that, the current line and all lines above it
312: * must be slid up to make room for the new line */
313: if(local.thing.linno < inst.thing.linno) /* insert case */
314: {
315: /* make room */
316: clear(); /*clear page index from current page up */
317: from = linptr;
318: linptr += strlen(linbuf) + 5;
319: to = linptr;
320: *linptr = '\0'; /*insure an eof mark*/
321: linptr[1] = '\0';
322: linptr[2] = '\0'; /* eof requires one 0 to end an expression
323: string and two to mark eof */
324: while(from != curptr)
325: *--to = *--from;
326: put();
327: update(); /* rebuild page index */
328: lbdptr=curptr=save;
329: return(0);
330: }
331: /* if we arrive at this place in the program, local.thing.linno is
332: * by default equal to inst.thing.linno and the action is to replace
333: * the current line with the new one. There are three possible
334: * vvariations in the replacement algorithm. 1) the new line
335: * and the old one are the same size in which case the action
336: * is a simple replacement. 2) the new line is shorter than the
337: * old one in which case the action is to replace the old line
338: * and slide the remaining txtbuf down to reclaim the left over
339: * space. 3) the new line is longer than the old one in which
340: * case the txtbuf above the current line must be slid up by
341: * an amount equal to the difference in length to make room
342: * for the new line */
343:
344: size = strlen(expr) - strlen(linbuf);
345: if(size == 0) /*case 1 */
346: {
347: put();
348: lbdptr=curptr=save;
349: return(0);
350: }
351: if(size > 0) /* case 2 */
352: {
353: put();
354: cover(lbdptr,curptr);
355: lbdptr=curptr=save;
356: return(0);
357:
358: }
359: clear(); /* case 3 by default of not being either 1 or 2 */
360: from = linptr;
361: linptr -= size;
362: to = linptr;
363: while(from != curptr)
364: *--to = *--from;
365: put();
366: update();
367: lbdptr=curptr=save;
368: return(0);
369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.