Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / sources / int / inkeyux.c
1 #include <stdio.h>\r
2 #include <signal.h>\r
3 #include <assert.h>\r
4 #include <string.h>\r
5 #include <ctype.h>\r
6 \r
7 #include <termio.h>\r
8 \r
9 \r
10 #include "graf/graf.h"\r
11 \r
12 #define KB_BACKSPACE    (int)'\b'       /* kb */\r
13 #define KB_ENTER        (int)'\r'       /* RT */\r
14 #define KB_TAB          (int)'\t'       /* TB */\r
15 #define KB_ESC          0x1b            /* EC */\r
16 \r
17 #define KB_HOME         -71     /* kh or HM */\r
18 #define KB_END          -79     /* EN */\r
19 #define KB_UP           -72     /* ku or UP */\r
20 #define KB_DOWN         -80     /* kd */\r
21 #define KB_LEFT         -75     /* kl */\r
22 #define KB_RIGHT        -77     /* kr */\r
23 #define KB_PGUP         -73     /* PU */\r
24 #define KB_PGDN         -81     /* PD */\r
25 #define KB_BACK_TAB     -15     /* BT */\r
26 #define KB_INS          -82     /* al */\r
27 #define KB_DEL          -83     /* DL */\r
28 \r
29 #define KB_F1           -59     /* k1 */\r
30 #define KB_F2           -60     /* k2 */\r
31 #define KB_F3           -61     /* k3 */\r
32 #define KB_F4           -62     /* k4 */\r
33 #define KB_F5           -63     /* k5 */\r
34 #define KB_F6           -64     /* k6 */\r
35 #define KB_F7           -65     /* k7 */\r
36 #define KB_F8           -66     /* k8 */\r
37 #define KB_F9           -67     /* k9 */\r
38 #define KB_F10          -68     /* k0 */\r
39 \r
40 #define KB_STR_EXISTS       1   /* string exists in tree or his prefix  */\r
41 #define KB_TOO_MANY_STRINGS 2   \r
42 #define KB_NULL_STRING      3\r
43 #define KB_OUT_OF_MEMORY    4\r
44 #define KB_OK               0\r
45 \r
46 \r
47 \r
48 #include "depend.h"\r
49 #include "genint.h"\r
50 #include "int.h"\r
51 #include "process.h"\r
52 #include "intproto.h"\r
53 \r
54 \r
55 #define TERMINAL 0\r
56 #define KEYBOARD 1\r
57 \r
58 static char *capability,*capability_value;\r
59 \r
60 typedef struct _tree_node *tree;    /* drzewo zawierajace ciagi znakow     */\r
61 struct _tree_node {                 /* odpowiadajace klawiszowi klawiatury */\r
62    int key;\r
63    tree way;\r
64    int outkey;\r
65 };    \r
66 \r
67 #ifndef NO_PROTOTYPES\r
68 static int tfirst(int);\r
69 static int tnext(void);\r
70 static void *___allocate_object(unsigned);\r
71 static void ___free_object(void *);\r
72 static char *object_str(char *);        /* allocate space and copy string */\r
73 static int __testkey(int*,int*);\r
74 static int getkey(void);\r
75 static int __inkey(void);\r
76 static void kbinit(void);\r
77 static tree new_tree_node(void);\r
78 static int _create_new_leaf(tree,int,unsigned char *,int);\r
79 static int inskey(int,char *);\r
80 #else\r
81 static int tfirst();\r
82 static int tnext();\r
83 static void *___allocate_object();\r
84 static void ___free_object();\r
85 static char *object_str();\r
86 static int __testkey();\r
87 static int getkey();\r
88 static int __inkey();\r
89 static void kbinit();\r
90 static tree new_tree_node();\r
91 static int _create_new_leaf();\r
92 static int inskey();\r
93 #endif\r
94 \r
95 \r
96 \r
97 \r
98 \r
99 #define object_kill(i) (___free_object(i),(i)=NULL)\r
100 #define object_new(type) ((type *)___allocate_object(sizeof(type)))\r
101 #define object_dim(i,type) ((type *)___allocate_object((i)*sizeof(type)))\r
102 \r
103 \r
104 \r
105 \r
106 #define KB_NDEF 0xff /* KN - key suppressed by inkey() */\r
107 \r
108 #define NODE_SIZE 100\r
109 \r
110 \r
111 #define QSIZE 256\r
112 static int cqueue[QSIZE];               /* implementacja kolejki */\r
113 static int qh=0,qt=0,qs=0;\r
114 static int bget(){\r
115    int c;\r
116    if( qs == 0 )  return -1;\r
117    c = cqueue[ qh++ ];\r
118    qh &= QSIZE - 1 ;\r
119    qs--;\r
120    return c;\r
121 }\r
122 static void bput( c )  int c; {\r
123    if( qs == QSIZE )  return;\r
124    cqueue[ qt++ ] = c;\r
125    qt &= QSIZE - 1 ;\r
126    qs++;\r
127 }\r
128 static int qq;\r
129 static int bfirst(){\r
130    if( qs == 0 )  return -1;\r
131    qq = qh + 1 ;\r
132    qq &= QSIZE - 1 ;\r
133    return  cqueue[ qh ];\r
134 }\r
135 static int bnext(){\r
136    int c;\r
137    if( qq == qt )  return -1;\r
138    c = cqueue[ qq++ ];\r
139    qq &= QSIZE - 1 ;\r
140    return c;\r
141 }\r
142 \r
143 \r
144 static tree troot=NULL;\r
145 \r
146 #ifndef NDEBUG\r
147 static FILE *f=NULL;\r
148 static void _show_tree(root,r) tree root;int r;{\r
149    int i,j;\r
150    for(i=0;(i<NODE_SIZE) && (root[i].key!=-1);i++){\r
151       for(j=0;j<r;j++) fprintf(f,"i");\r
152       fflush(f);\r
153       fprintf(f,"%d ",root[i].key);fflush(f);\r
154       if(root[i].way==NULL){\r
155          fprintf(f,"%d\n",root[i].outkey);fflush(f);\r
156       }else _show_tree(root[i].way,r+1);\r
157    }\r
158 }\r
159 static void show_tree(){\r
160    f=fopen("show_tree","a");\r
161    if(f==NULL){printf("cant open");exit(7);}\r
162    fprintf(f,"%lx\n",troot);fflush(f);\r
163    _show_tree(troot,0);\r
164    fprintf(f,"********************\n");\r
165    fclose(f);\r
166 }\r
167 #endif\r
168 \r
169 \r
170 #define NO_CHARS        0\r
171 #define PART_SUBSTRING  1\r
172 #define SUBSTRING       2\r
173 #define STRING          3\r
174 #define NO_MATCH        4\r
175 \r
176 static int __testkey(outkey,to_take) int *outkey,*to_take;\r
177 {\r
178    int c,i;\r
179    tree tact;\r
180 \r
181    tact=troot;\r
182    c=bfirst();\r
183 \r
184    if(c==-1) return NO_CHARS; /* buffer empty - wait for char */\r
185 \r
186    *to_take=1;\r
187 \r
188    for(;;){\r
189       for(i=0;i<NODE_SIZE;i++){\r
190          if(tact[i].key==-1){ i=NODE_SIZE; break; }\r
191          if(tact[i].key==c)\r
192             if(tact[i].way!=NULL){\r
193                c=bnext();\r
194                (*to_take)++;\r
195                if(c==-1){\r
196                   *outkey=tact[i].outkey;\r
197                   if(*outkey != -1)  return SUBSTRING;\r
198                   else               return PART_SUBSTRING;\r
199                }\r
200                tact=tact[i].way;\r
201                break;\r
202             }\r
203             else{\r
204                *outkey = tact[i].outkey;\r
205                return STRING;\r
206             }\r
207       }\r
208       if( i==NODE_SIZE )   return NO_MATCH;\r
209    } \r
210 }\r
211 \r
212 \r
213 static void (*prev_fun)()=NULL;\r
214 static void alarm_fun(){}\r
215 \r
216 \r
217 static int getkey(){\r
218    int c;\r
219    prev_fun = signal( SIGALRM, alarm_fun );\r
220    alarm(1);\r
221    c = getchar();\r
222    alarm(0);\r
223    signal( SIGALRM, prev_fun );\r
224    return c;\r
225 }\r
226 \r
227 \r
228 \r
229 static int __inkey()\r
230 {\r
231    int c,i,outkey,chars;\r
232    if(troot==NULL){printf("Not initialized\n\r");exit(7);}\r
233 \r
234    alarm(0);\r
235 \r
236    for(;;){\r
237 \r
238       i=__testkey(&outkey,&chars);\r
239 \r
240       switch( i ){\r
241 \r
242          case NO_CHARS :\r
243             c = getkey();\r
244             if( c != -1 )   bput( c );\r
245             else  return 0;\r
246             break;\r
247 \r
248          case PART_SUBSTRING :\r
249             c = getkey();\r
250             if( c==-1 ) return bget();\r
251             bput( c );\r
252             break;\r
253 \r
254          case SUBSTRING :\r
255             c = getkey();\r
256             if( c==-1 ){\r
257                while( chars-- )  bget();\r
258                return outkey;\r
259             }\r
260             bput( c );\r
261             break;\r
262 \r
263          case STRING :\r
264             while( chars-- )  bget();\r
265             return outkey;\r
266             break;\r
267 \r
268          case NO_MATCH :\r
269             return bget();\r
270             break;\r
271       }\r
272    }\r
273 }\r
274 \r
275 \r
276 static struct termio term_state,term_new;\r
277 \r
278 int inkey( dummy )\r
279    void *dummy;\r
280 {  /* podaj znak z klawiatury - zapominanie KB_NDEF */\r
281    static int first_time=1;\r
282    int k;\r
283 \r
284    if( first_time ){  kbinit(); first_time=0; }\r
285 \r
286    ioctl(fileno(stdin),TCGETA,&term_state);  /* RAW MODE */\r
287    term_new = term_state;\r
288    term_new.c_lflag&=~(ISIG|ICANON|ECHO);   /* echo,canonical line processing */\r
289                                             /* signal processing = OFF */\r
290    term_new.c_iflag&=~(ICRNL|INLCR);        /* conversions OFF */\r
291    term_new.c_oflag=0;\r
292    term_new.c_cc[VEOF]='\1';                /* every char flushed immedietly */\r
293    ioctl(fileno(stdin),TCSETA,&term_new);\r
294 \r
295    do k=__inkey(); while(k==KB_NDEF);\r
296 \r
297    ioctl(fileno(stdin),TCSETA,&term_state);  /* PREVIOUS MODE */\r
298 \r
299    return k;\r
300 }\r
301 \r
302 \r
303 static tree new_tree_node(){\r
304    tree p;\r
305    int i;\r
306    p=(tree)object_dim(NODE_SIZE+1,struct _tree_node);\r
307    p++;\r
308    for(i=0;i<NODE_SIZE;i++){\r
309       p[i].key=p[i].outkey=-1;\r
310       p[i].way=NULL;\r
311    }\r
312    return p;\r
313 }\r
314 \r
315 \r
316 static int inskey(ch,str)\r
317    int ch;\r
318    char *str;\r
319 {\r
320    tree tact=troot;\r
321    int i;\r
322 \r
323    if(troot==NULL) return KB_OUT_OF_MEMORY;\r
324    if(str==NULL || (!(*str))) return KB_NULL_STRING;\r
325 \r
326    for(;;){\r
327       for(i=0;i<NODE_SIZE;i++){\r
328          if(tact[i].key==-1){\r
329             tact[i].key=(int)(*(str++));\r
330             return _create_new_leaf(tact,i,str,ch);\r
331          }\r
332          if(tact[i].key==(int)(*str)){\r
333             str++;\r
334             if(tact[i].way==NULL)\r
335                if( *str!='\0' )  return _create_new_leaf(tact,i,str,ch);\r
336                else              return KB_STR_EXISTS;\r
337             if( *str=='\0' ){\r
338                tact[i].outkey=ch;\r
339                return KB_OK;\r
340             }\r
341             tact=tact[i].way;\r
342             break;\r
343          }\r
344       }\r
345       if(i==NODE_SIZE) return KB_TOO_MANY_STRINGS;\r
346    }\r
347 }\r
348 \r
349 \r
350 static int _create_new_leaf(tact,i,str,ch)\r
351    tree tact;\r
352    int i,ch;\r
353    unsigned char *str;\r
354 {\r
355    while(*str!='\0'){\r
356       tact[i].way=new_tree_node();\r
357       tact[i].way[-1].way=tact;\r
358       tact=tact[i].way;\r
359       i=0;\r
360       tact[0].key=(int)(*(str++));\r
361    } \r
362    tact[i].outkey=ch;\r
363    return KB_OK;\r
364 }\r
365 \r
366 \r
367 static struct { int key; char capability[3]; } tab[]={\r
368 \r
369         { KB_NDEF       , "KN" },\r
370         { KB_BACKSPACE  , "kb" },\r
371         { KB_ENTER      , "RT" },\r
372         { KB_HOME       , "kh" },\r
373         { KB_HOME       , "HM" },\r
374         { KB_END        , "EN" },\r
375         { KB_UP         , "ku" },\r
376         { KB_UP         , "UP" },\r
377         { KB_DOWN       , "kd" },\r
378         { KB_LEFT       , "kl" },\r
379         { KB_RIGHT      , "kr" },\r
380         { KB_PGUP       , "PU" },\r
381         { KB_PGDN       , "PD" },\r
382         { KB_BACK_TAB   , "BT" },\r
383         { KB_TAB        , "TB" },\r
384         { KB_ESC        , "EC" },\r
385         { KB_INS        , "al" },\r
386         { KB_DEL        , "DL" },\r
387         { KB_F1         , "k1" },\r
388         { KB_F2         , "k2" },\r
389         { KB_F3         , "k3" },\r
390         { KB_F4         , "k4" },\r
391         { KB_F5         , "k5" },\r
392         { KB_F6         , "k6" },\r
393         { KB_F7         , "k7" },\r
394         { KB_F8         , "k8" },\r
395         { KB_F9         , "k9" },\r
396         { KB_F10        , "k0" }\r
397    };\r
398 \r
399 \r
400 static void kb_install(){\r
401    int i;\r
402    for(i=0;i<sizeof(tab)/sizeof(*tab);i++){\r
403       if(tab[i].capability[0]!=capability[0]) continue;\r
404       if(tab[i].capability[1]!=capability[1]) continue;\r
405       if(capability_value==NULL) return;\r
406       if(capability[2]!='='){\r
407          if( capability_value!=NULL) object_kill(capability_value);\r
408          return;\r
409       }\r
410       {\r
411          int err = inskey(tab[i].key,capability_value);\r
412          if(err==KB_OK) return;\r
413          if(err==KB_STR_EXISTS || err==KB_NULL_STRING){\r
414             object_kill(capability_value);\r
415             return;\r
416          }\r
417          printf("Capability %2.2s cannot be inserted:",capability);\r
418          if(err==KB_TOO_MANY_STRINGS) printf("too many strings\n\r");\r
419          if(err==KB_OUT_OF_MEMORY   ) printf("out of memory\n\r");\r
420          exit(7);\r
421       }\r
422       return;\r
423    }\r
424    if(capability_value!=NULL) object_kill(capability_value);\r
425 }\r
426 \r
427 \r
428 static void kbinit()                   /* inicjalizacja klawiatury  */\r
429 {                                      /* RAW MODE                  */\r
430    char *s,*s1;\r
431    int i,err;\r
432 \r
433    troot=new_tree_node();\r
434    troot[-1].way=NULL;\r
435 \r
436    capability="DL=";\r
437    capability_value=object_str("\177");\r
438    kb_install();\r
439 \r
440    if(tfirst(KEYBOARD)==0){\r
441       kb_install();\r
442       while(tnext()==0){\r
443          kb_install();\r
444       }\r
445    }\r
446 \r
447    if(tfirst(TERMINAL)==0){\r
448       kb_install();\r
449       while(tnext()==0){\r
450          kb_install();\r
451       }\r
452    }\r
453 \r
454 }\r
455 \r
456 \r
457 \r
458 \r
459 /*   FUNCTIONS for search through one TERMCAP entry   */\r
460 \r
461 \r
462 static char *termcap=NULL;\r
463 static char *keybcap=NULL;\r
464 \r
465 #ifndef NO_PROTOTYPES\r
466 static char *envset(char *,char*);\r
467 static char *findchar(char *,char);\r
468 static int convert(char *,char *,int);\r
469 static int next_char(FILE *);\r
470 static int find_name(FILE *,char *);\r
471 #else\r
472 static char *envset();\r
473 static char *findchar();\r
474 static int convert();\r
475 static int next_char();\r
476 static int find_name();\r
477 #endif\r
478 \r
479 \r
480 static char *findchar(str,ch) char *str,ch;{\r
481    if(str==NULL) return NULL;\r
482    while( *str!='\0'  &&  *str!=ch )  str++;\r
483    if(*str=='\0') return NULL;\r
484    return str;\r
485 }\r
486 \r
487 static char *tgetent(dev)\r
488                             /* gets info from variable TERMCAP  */ \r
489                             /* or var INKEY  or file /etc/inkey */\r
490 int dev;{\r
491 \r
492  if(dev==TERMINAL){\r
493    if(termcap==NULL)   termcap=envset("TERMCAP","termcap");\r
494    if(termcap==NULL){\r
495       fprintf(stderr,"\n\rfile [/etc/]termcap not found\n\r");\r
496       fflush(stderr);exit(7);\r
497    }\r
498    return termcap;\r
499  }else\r
500  if(dev==KEYBOARD){\r
501     if(keybcap==NULL)  keybcap=envset("INKEY","inkey");\r
502     return keybcap;\r
503  }else{ printf("bad device for tgetent \n\r"); exit(7); }\r
504 }\r
505 \r
506 \r
507 \r
508 \r
509 static char stat_value[100];\r
510 \r
511 static int tfirst(dev)\r
512    int dev;\r
513 {\r
514    char *value;\r
515    capability=tgetent(dev);\r
516    if(capability==NULL) return 1;\r
517    return tnext();\r
518 }\r
519 static int tnext(){\r
520    char *value,*colon;\r
521    do{\r
522       capability=findchar(capability,':');\r
523       if(capability==NULL) return 1;\r
524       capability++;\r
525       if(*capability=='\0') return 1;\r
526    } while( capability[0]==' ' || capability[0]=='\t' );\r
527    value=findchar(capability,'=');\r
528    colon=findchar(capability,':');\r
529    if( value==NULL || ( colon!=NULL && value!=NULL && colon<value ) ){\r
530       capability_value=object_str("");\r
531       return 0;\r
532    }\r
533    value++;\r
534    if(*value=='\0') return 1;\r
535    convert(stat_value,value,sizeof(stat_value));\r
536    capability_value=object_str(stat_value);\r
537    return 0;\r
538 }\r
539 \r
540 \r
541 static int convert(ptr,tptr,ptr_size) char *ptr,*tptr; int ptr_size; {\r
542    int i;\r
543    char c;\r
544    while( (tptr!=NULL) && (*tptr!=':') && (*tptr!='\0') )\r
545       switch(*tptr){\r
546          case '\\':tptr++;\r
547                    switch(*tptr){\r
548                       case 'E' :tptr++;ptr_size--;*(ptr++)='\x1b';break;\r
549                       case 'n' :tptr++;ptr_size--;*(ptr++)='\n';break;\r
550                       case 'r' :tptr++;ptr_size--;*(ptr++)='\r';break;\r
551                       case 't' :tptr++;ptr_size--;*(ptr++)='\t';break;\r
552                       case 'b' :tptr++;ptr_size--;*(ptr++)='\b';break;\r
553                       case 'f' :tptr++;ptr_size--;*(ptr++)='\f';break;\r
554                       case '\\':tptr++;ptr_size--;*(ptr++)='\\';break;\r
555                       case '^' :tptr++;ptr_size--;*(ptr++)='^';break;\r
556                       default  :*ptr='\0';\r
557                                 for(i=0;i<3;i++){\r
558                                    if(*tptr<'0' || *tptr>'7') return 1;\r
559                                    *ptr*=8;\r
560                                    *ptr+=*(tptr++)-'0';\r
561                                 }\r
562                                 ptr++; ptr_size--;\r
563                    }\r
564                    break;\r
565          case '^': tptr++;\r
566                    c=*(tptr++);\r
567                    *(ptr++)=(char)((toupper(c))-'A'+1); ptr_size--;\r
568                    break;\r
569          default: *(ptr++)=*(tptr++); ptr_size--; \r
570       } \r
571    *ptr='\0';\r
572    if( ptr_size<=0 ){\r
573       fprintf(stderr,"buffer exceeded in convert(%s)",__FILE__);\r
574       fflush(stderr);\r
575       exit(7);\r
576    }\r
577    return 0;\r
578 }\r
579 \r
580 \r
581 /*     FUNCTIONS looking for entries in /ETC/TERMCAP      */\r
582 \r
583 \r
584 \r
585 static char etcname[80];\r
586 static char termname[80];\r
587 static char *fname;\r
588 \r
589 \r
590 static char *envset(envname,envfile) char *envname,*envfile;{\r
591    extern char *getenv();\r
592    char *TERM=getenv("TERM");\r
593    char *env=getenv(envname);\r
594    char *str,*ptr;\r
595    FILE *f;\r
596    int c,continued=1;\r
597 \r
598    ptr=str=object_dim(32000,char);\r
599    if(str==NULL){\r
600       fprintf(stderr,"Out of memory.\n");\r
601       fflush(stderr);\r
602       exit(7);\r
603    }\r
604 \r
605    if(TERM==NULL){\r
606       fprintf(stderr,"\n\renvironment variable TERM not found\n\r");\r
607       fflush(stderr);\r
608       exit(7);\r
609    }\r
610 \r
611    strcpy(termname,TERM);\r
612 \r
613    f=fopen(env,"r");\r
614    if( f==NULL )  f=fopen(envfile,"r");  else  fname=env;\r
615    if( f==NULL )  f=fopen(strcat(strcpy(etcname,"/etc/"),envfile),"r");\r
616    else           fname=envfile;\r
617    if( f==NULL )  return NULL;\r
618    else           fname=etcname;\r
619 \r
620    while( continued ){\r
621 \r
622       char *rev,*tnm;\r
623 \r
624       if( find_name(f,termname)==0 )   return object_str(":");\r
625 \r
626       *(ptr++)=':';\r
627       c=' ';\r
628       do{\r
629          c=next_char(f);\r
630          if( c!='\0' ) *(ptr++)=(char)c;\r
631       }while( c!='\0' );\r
632 \r
633       *(ptr)='\0';\r
634       rev=ptr-1;\r
635       while( rev>str && rev[-1]!=':' )  rev--;\r
636       if( rev[0]=='t' && rev[1]=='c' ){\r
637          ptr=rev-1;\r
638          rev+=3;\r
639          tnm=termname;\r
640          while( *rev!=':' ) *(tnm++)=*(rev++);\r
641          *tnm='\0';\r
642          continued=1;\r
643       }else  continued=0;\r
644 \r
645    }\r
646 \r
647    ptr=object_str(str);\r
648    object_kill(str);\r
649    return ptr;\r
650 \r
651 }\r
652 \r
653 static int find_name(f,termname) FILE *f; char *termname;{\r
654    int i,c,lastc,found=0;\r
655    fseek(f,0L,0);\r
656 \r
657    do{\r
658 \r
659       do{\r
660          c=fgetc(f);\r
661          if(c==EOF)  return 0;\r
662          if(c=='#' || c=='\t' || c==':' || c=='\n')\r
663             while(c!='\n'){\r
664                lastc=c;\r
665                c=fgetc(f);\r
666                if(c==EOF)  return 0;\r
667                if( lastc=='\\' ) c=' ';\r
668             }\r
669       }while(c=='\n');\r
670 \r
671       while( !found ){\r
672          for(i=0;termname[i]!='\0';i++){\r
673             if((char)c!=termname[i]) break;\r
674             c=fgetc(f);\r
675          }\r
676          if( termname[i]=='\0' ){ found=1; break; }\r
677          while( isalpha((char)c) )  c=fgetc(f);\r
678          if( c=='|' )  c=fgetc(f);\r
679          else{ ungetc('#',f); break; }\r
680       }\r
681 \r
682    } while( !found );\r
683 \r
684    while(c!=':'){\r
685       c=fgetc(f);\r
686       if(c==EOF)  return 0;\r
687    }\r
688 \r
689    return 1;\r
690 }\r
691 \r
692 \r
693 static int next_char(f) FILE *f;{\r
694    int c;\r
695    static int lastc='\0';\r
696    if( lastc!='\0' ){\r
697       c=lastc;\r
698       lastc='\0';\r
699       return c;\r
700    }\r
701    c=fgetc(f);\r
702    if( c==EOF || c=='\n' )  return '\0';\r
703    if( c=='\\' ){\r
704       c=fgetc(f);\r
705       if( c=='\n' ){\r
706          while( c=='\n' || c=='\t' || c==':' || c==' ' )  c=fgetc(f);\r
707          return c;\r
708       }\r
709       lastc=c;\r
710       return '\\';\r
711    }\r
712    return c;\r
713 }\r
714 \r
715 \r
716 \r
717 \r
718 static void *___allocate_object(size) unsigned size;{\r
719    char *p;\r
720    extern void *calloc();\r
721    if(size==0) return NULL;\r
722    p=calloc(size,1);\r
723    if( p==NULL ){\r
724       printf("\r\n");\r
725       printf("=======================================\r\n");\r
726       printf("Memory overflow ... \r\n");\r
727       printf("=======================================\r\n");\r
728       fflush(stdout);\r
729       system("stty sane");\r
730       exit(7);\r
731    }\r
732    return (void *)p;\r
733 }\r
734 \r
735 static void ___free_object(ff) void *ff;{\r
736    assert(ff!=NULL);\r
737    free((char *)ff);\r
738 }\r
739 \r
740 static char *object_str(str) char *str;{\r
741    char *buf=object_dim(strlen(str)+1,char);\r
742    strcpy(buf,str);\r
743    return buf;\r
744 }\r