This is rc.c in view mode; [Download] [Up]
/* rc file parser */ #include <stdio.h> #include "zstr.h" #include "macro.h" #include "cmd.h" #include "bw.h" #include "help.h" #include "vs.h" #include "va.h" #include "menu.h" #include "umath.h" #include "uedit.h" #include "pw.h" #include "path.h" #include "w.h" #include "tw.h" #include "termcap.h" #include "rc.h" static struct context { struct context *next; char *name; KMAP *kmap; } *contexts=0; /* List of named contexts */ /* Find a context of a given name- if not found, one with an empty kmap * is created. */ KMAP *getcontext(name) char *name; { struct context *c; for(c=contexts;c;c=c->next) if(!zcmp(c->name,name)) return c->kmap; c=(struct context *)malloc(sizeof(struct context)); c->next=contexts; c->name=zdup(name); contexts=c; return c->kmap=mkkmap(); } OPTIONS *options=0; extern int mid, dspasis, dspctrl, force, help, pgamnt, square, csmode, nobackups, lightoff, exask, skiptop, noxon, lines, staen, columns, Baud, dopadding, orphan, marking, beep, keepup, nonotice; extern char *backpath; OPTIONS pdefault= { 0, 0, 0, 0, 76, 0, 0, 8, ' ', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; OPTIONS fdefault= { 0, 0, 0, 0, 76, 0, 0, 8, ' ', 1, "main", "\\i%n %m %M", " %S Ctrl-K H for help", 0, 0, 0, 0, 0, 0 }; void setopt(n,name) OPTIONS *n; char *name; { OPTIONS *o; for(o=options;o;o=o->next) if(rmatch(o->name,name)) { *n= *o; return; } *n=fdefault; } /* Set a global or local option * returns 0 for no such option, * 1 for option accepted * 2 for option + argument accepted */ struct glopts { char *name; /* Option name */ int type; /* 0 for global option flag 1 for global option numeric 2 for global option string 4 for local option flag 5 for local option numeric 6 for local option string 7 for local option numeric+1 */ int *set; /* Address of global option */ char *addr; /* Local options structure member address */ char *yes; /* Message if option was turned on, or prompt string */ char *no; /* Message if option was turned off */ char *menu; /* Menu string */ int ofst; /* Local options structure member offset */ int low; /* Low limit for numeric options */ int high; /* High limit for numeric options */ } glopts[]= { {"overwrite", 4, 0, (char *)&fdefault.overtype, "Overtype mode", "Insert mode", "T Overtype "}, {"autoindent", 4, 0, (char *)&fdefault.autoindent, "Autoindent enabled", "Autindent disabled", "I Autoindent "}, {"wordwrap", 4, 0, (char *)&fdefault.wordwrap, "Wordwrap enabled", "Wordwrap disabled", "Word wrap "}, {"tab", 5, 0, (char *)&fdefault.tab, "Tab width (%d): ", 0, "D Tab width ",0,1,64}, {"lmargin", 7, 0, (char *)&fdefault.lmargin, "Left margin (%d): ", 0, "Left margin ",0,1,64}, {"rmargin", 7, 0, (char *)&fdefault.rmargin, "Right margin (%d): ", 0, "Right margin ",0,8,256}, {"square", 0, &square, 0, "Rectangle mode", "Text-stream mode", "X Rectangle mode " }, {"indentc", 5, 0, (char *)&fdefault.indentc, "Indent char %d (SPACE=32, TAB=9, ^C to abort): ", 0, " Indent char ",0,0,255}, {"istep", 5, 0, (char *)&fdefault.istep, "Indent step %d (^C to abort): ", 0, " Indent step ",0,1,64}, {"french", 4, 0, (char *)&fdefault.french, "One space after periods for paragraph reformat", "Two spaces after periods for paragraph reformat", " french spacing "}, {"spaces", 4, 0, (char *)&fdefault.spaces, "Inserting spaces when tab key is hit", "Inserting tabs when tab key is hit", " no tabs "}, {"mid", 0, &mid, 0, "Cursor will be recentered on scrolls", "Cursor will not be recentered on scroll", "Center on scroll " }, {"linums", 4, 0, (char *)&fdefault.linums, "Line numbers enabled", "Line numbers disabled", "N Line numbers "}, {"marking", 0, &marking, 0, "Anchored block marking on", "Anchored block marking off", "Marking " }, {"asis", 0, &dspasis, 0, "Characters above 127 shown as-is", "Characters above 127 shown in inverse", "Meta chars as-is " }, {"force", 0, &force, 0, "Last line forced to have NL when file saved", "Last line not forces to have NL", "Force last NL " }, {"nobackups", 0, &nobackups, 0, "Backup files will not be made", "Backup files will be made", " Disable backups " }, {"lightoff", 0, &lightoff, 0, "Highlighting turned off after block operations", "Highlighting not turned off after block operations", "Auto unmark " }, {"exask", 0, &exask, 0, "Prompt for filename in save & exit command", "Don't prompt for filename in save & exit command", "Exit ask "}, {"beep", 0, &beep, 0, "Warning bell enabled", "Warning bell disabled", "Beeps " }, {"nosta", 0, &staen, 0, "Top-most status line disabled", "Top-most status line enabled", " Disable status line " }, {"keepup", 0, &keepup, 0, "Status line updated constantly", "Status line updated once/sec", " Fast status line " }, {"pg", 1, &pgamnt, 0, "Lines to keep for PgUp/PgDn or -1 for 1/2 window (%d): ", 0, " No. PgUp/PgDn lines ", 0, -1, 64 }, {"csmode", 0, &csmode, 0, "Start search after a search repeats previous search", "Start search always starts a new search", "Continued search " }, {"rdonly", 4, 0, (char *)&fdefault.readonly, "Read only", "Full editing", "O Read only "}, {"backpath", 2, (int *)&backpath, 0, "Backup files stored in (%s): ", 0, "Path to backup files " }, {"nonotice", 0, &nonotice, 0, 0, 0, 0 }, {"noxon", 0, &noxon, 0, 0, 0, 0 }, {"orphan", 0, &orphan, 0, 0, 0, 0 }, {"help", 0, &help, 0, 0, 0, 0 }, {"dopadding", 0, &dopadding, 0, 0, 0, 0 }, {"lines", 1, &lines, 0, 0, 0, 0, 0, 2, 1024 }, {"baud", 1, &Baud, 0, 0, 0, 0, 0, 50, 32767 }, {"columns", 1, &columns, 0, 0, 0, 0, 0, 2, 1024 }, {"skiptop", 1, &skiptop, 0, 0, 0, 0, 0, 0, 64 }, { 0, 0, 0 } }; int isiz=0; void izopts() { int x; for(x=0;glopts[x].name;++x) switch(glopts[x].type) { case 4: case 5: case 6: case 7: case 8: glopts[x].ofst=glopts[x].addr-(char *)&fdefault; } isiz=1; } int glopt(s,arg,options,set) char *s, *arg; OPTIONS *options; { int val; int ret=0; int st=1; int x; if(!isiz) izopts(); if(s[0]=='-') st=0, ++s; for(x=0;glopts[x].name;++x) if(!zcmp(glopts[x].name,s)) { switch(glopts[x].type) { case 0: if(set) *glopts[x].set=st; break; case 1: if(set && arg) { sscanf(arg,"%d",&val); if(val>=glopts[x].low && val<=glopts[x].high) *glopts[x].set=val; } break; case 2: if(set) if(arg) *(char **)glopts[x].set=zdup(arg); else *(char **)glopts[x].set=0; break; case 4: if(options) *(int *)((char *)options+glopts[x].ofst)=st; else if(set==2) *(int *)((char *)&fdefault+glopts[x].ofst)=st; break; case 5: if(arg) if(options) { sscanf(arg,"%d",&val); if(val>=glopts[x].low && val<=glopts[x].high) *(int *)((char *)options+glopts[x].ofst)=val; } else if(set==2) { sscanf(arg,"%d",&val); if(val>=glopts[x].low && val<=glopts[x].high) *(int *)((char *)&fdefault+glopts[x].ofst)=val; } break; case 7: if(arg) { int zz=0; sscanf(arg,"%d",&zz); if(zz>=glopts[x].low && zz <=glopts[x].high) { --zz; if(options) *(int *)((char *)options+glopts[x].ofst)=zz; else if(set==2) *(int *)((char *)&fdefault+glopts[x].ofst)=zz; } } break; } if((glopts[x].type&3)==0 || !arg) return 1; else return 2; } if(!zcmp(s,"lmsg")) { if(arg) { if(options) options->lmsg=zdup(arg); else if(set==2) fdefault.lmsg=zdup(arg); ret=2; } else ret=1; } else if(!zcmp(s,"rmsg")) { if(arg) { if(options) options->rmsg=zdup(arg); else if(set==2) fdefault.rmsg=zdup(arg); ret=2; } else ret=1; } else if(!zcmp(s,"keymap")) { if(arg) { int y; for(y=0;!cwhitel(arg[y]);++y); if(!arg[y]) arg[y]=0; if(options && y) options->context=zdup(arg); ret=2; } else ret=1; } else if(!zcmp(s,"mnew")) { if(arg) { int sta; if(options) options->mnew=mparse(NULL,arg,&sta); else if(set==2) fdefault.mnew=mparse(NULL,arg,&sta); ret=2; } else ret=1; } else if(!zcmp(s,"mold")) { if(arg) { int sta; if(options) options->mold=mparse(NULL,arg,&sta); else if(set==2) fdefault.mold=mparse(NULL,arg,&sta); ret=2; } else ret=1; } else if(!zcmp(s,"msnew")) { if(arg) { int sta; if(options) options->msnew=mparse(NULL,arg,&sta); else if(set==2) fdefault.msnew=mparse(NULL,arg,&sta); ret=2; } else ret=1; } else if(!zcmp(s,"msold")) { if(arg) { int sta; if(options) options->msold=mparse(NULL,arg,&sta); else if(set==2) fdefault.msold=mparse(NULL,arg,&sta); ret=2; } else ret=1; } done: return ret; } static int optx=0; int doabrt1(bw,xx) BW *bw; int *xx; { free(xx); return -1; } int doopt1(bw,s,xx,notify) BW *bw; char *s; int *xx; int *notify; { int ret=0; int x= *xx; int v; free(xx); switch(glopts[x].type) { case 1: v=calc(bw,s); if(merr) msgnw(bw,merr), ret= -1; else if(v>=glopts[x].low && v<=glopts[x].high) *glopts[x].set=v; else msgnw(bw,"Value out of range"), ret= -1; break; case 2: if(s[0]) *(char **)glopts[x].set=zdup(s); break; case 5: v=calc(bw,s); if(merr) msgnw(bw,merr), ret= -1; else if(v>=glopts[x].low && v<=glopts[x].high) *(int *)((char *)&bw->o+glopts[x].ofst)=v; else msgnw(bw,"Value out of range"), ret= -1; break; case 7: v=calc(bw,s)-1.0; if(merr) msgnw(bw,merr), ret= -1; else if(v>=glopts[x].low && v<=glopts[x].high) *(int *)((char *)&bw->o+glopts[x].ofst)=v; else msgnw(bw,"Value out of range"), ret= -1; break; } vsrm(s); bw->b->o=bw->o; wfit(bw->parent->t); updall(); if(notify) *notify=1; return ret; } int doopt(m,x,object,flg) MENU *m; void *object; { BW *bw=m->parent->win->object; int *xx; char buf[80]; int *notify=m->parent->notify; switch(glopts[x].type) { case 0: if(!flg) *glopts[x].set= !*glopts[x].set; else if(flg==1) *glopts[x].set= 1; else *glopts[x].set=0; uabort(m,MAXINT); msgnw(bw,*glopts[x].set?glopts[x].yes:glopts[x].no); break; case 4: if(!flg) *(int *)((char *)&bw->o+glopts[x].ofst)= !*(int *)((char *)&bw->o+glopts[x].ofst); else if(flg==1) *(int *)((char *)&bw->o+glopts[x].ofst)=1; else *(int *)((char *)&bw->o+glopts[x].ofst)=0; uabort(m,MAXINT); msgnw(bw,*(int *)((char *)&bw->o+glopts[x].ofst)?glopts[x].yes:glopts[x].no); if(glopts[x].ofst==(char *)&fdefault.readonly-(char *)&fdefault) bw->b->rdonly=bw->o.readonly; break; case 1: sprintf(buf,glopts[x].yes,*glopts[x].set); xx=(int *)malloc(sizeof(int)); *xx=x; m->parent->notify=0; uabort(m,MAXINT); if(wmkpw(bw,buf,NULL,doopt1,NULL,doabrt1,utypebw,xx,notify)) return 0; else return -1; case 2: if(*(char **)glopts[x].set) sprintf(buf,glopts[x].yes,*(char **)glopts[x].set); else sprintf(buf,glopts[x].yes,""); xx=(int *)malloc(sizeof(int)); *xx=x; m->parent->notify=0; uabort(m,MAXINT); if(wmkpw(bw,buf,NULL,doopt1,NULL,doabrt1,utypebw,xx,notify)) return 0; else return -1; case 5: sprintf(buf,glopts[x].yes,*(int *)((char *)&bw->o+glopts[x].ofst)); goto in; case 7: sprintf(buf,glopts[x].yes,*(int *)((char *)&bw->o+glopts[x].ofst)+1); in: xx=(int *)malloc(sizeof(int)); *xx=x; m->parent->notify=0; uabort(m,MAXINT); if(wmkpw(bw,buf,NULL,doopt1,NULL,doabrt1,utypebw,xx,notify)) return 0; else return -1; } if(notify) *notify=1; bw->b->o=bw->o; wfit(bw->parent->t); updall(); return 0; } int doabrt(m,x,s) MENU *m; char **s; { optx=x; for(x=0;s[x];++x) free(s[x]); free(s); return -1; } int umode(bw) BW *bw; { int size; char **s; int x; bw->b->o.readonly=bw->o.readonly=bw->b->rdonly; for(size=0;glopts[size].menu;++size); s=(char **)malloc(sizeof(char *)*(size+1)); for(x=0;x!=size;++x) { s[x]=(char *)malloc(40); switch(glopts[x].type) { case 0: sprintf(s[x],"%s%s",glopts[x].menu,*glopts[x].set?"ON":"OFF"); break; case 1: sprintf(s[x],"%s%d",glopts[x].menu,*glopts[x].set); break; case 2: zcpy(s[x],glopts[x].menu); break; case 4: sprintf(s[x],"%s%s",glopts[x].menu,*(int *)((char *)&bw->o+glopts[x].ofst)?"ON":"OFF"); break; case 5: sprintf(s[x],"%s%d",glopts[x].menu,*(int *)((char *)&bw->o+glopts[x].ofst)); break; case 7: sprintf(s[x],"%s%d",glopts[x].menu,*(int *)((char *)&bw->o+glopts[x].ofst)+1); break; } } s[x]=0; if(mkmenu(bw,s,doopt,doabrt,NULL,optx,s,NULL)) return 0; else return -1; } /* Process rc file * Returns 0 if the rc file was succefully processed * -1 if the rc file couldn't be opened * 1 if there was a syntax error in the file */ int nhelp=0; /* No. help screens so far */ int procrc(cap,name) CAP *cap; char *name; { OPTIONS *o=0; /* Current options */ KMAP *context=0; /* Current context */ unsigned char buf[1024]; /* Input buffer */ FILE *fd; /* rc file */ int line=0; /* Line number */ int err=0; /* Set to 1 if there was a syntax error */ ossep(zcpy(buf,name)); #ifdef __MSDOS__ fd=fopen(buf,"rt"); #else fd=fopen(buf,"r"); #endif if(!fd) return -1; /* Return if we couldn't open the rc file */ fprintf(stderr,"Processing '%s'...",name); fflush(stderr); while(++line, fgets(buf,1024,fd)) switch(buf[0]) { case ' ': case '\t': case '\n': case '\f': case 0: break; /* Skip comment lines */ case '*': /* Select file types for file-type dependant options */ { int x; o=(OPTIONS *)malloc(sizeof(OPTIONS)); *o=fdefault; for(x=0;buf[x] && buf[x]!='\n' && buf[x]!=' ' && buf[x]!='\t';++x); buf[x]=0; o->next=options; options=o; o->name=zdup(buf); } break; case '-': /* Set an option */ { unsigned char *opt=buf+1; int x; unsigned char *arg=0; for(x=0;buf[x] && buf[x]!='\n' && buf[x]!=' ' && buf[x]!='\t';++x); if(buf[x] && buf[x]!='\n') { buf[x]=0; for(arg=buf+ ++x;buf[x] && buf[x]!='\n';++x); } buf[x]=0; if(!glopt(opt,arg,o,2)) { err=1; fprintf(stderr,"\n%s %d: Unknown option %s",name,line,opt); } } break; case '{': /* Enter help text */ { int bfl; struct help *tmp=(struct help *)malloc(sizeof(struct help)); nhelp++; tmp->next=first_help; first_help=tmp; tmp->name=vsncpy(NULL,0,sz(buf+1)-1); help_names=vaadd(help_names,tmp->name); tmp->hlptxt=0; tmp->hlpsiz=0; tmp->hlpbsz=0; tmp->hlplns=0; up: if(++line, !fgets(buf,256,fd)) { err=1; fprintf(stderr,"\n%s %d: End of joerc file occured before end of help text",name,line); break; } if(buf[0]=='}') { if(!hlptxt) hlptxt=tmp->hlptxt, hlpsiz=tmp->hlpsiz, hlpbsz=tmp->hlpbsz, hlplns=tmp->hlplns; continue; } bfl=zlen(buf); if(tmp->hlpsiz+bfl>tmp->hlpbsz) { if(tmp->hlptxt) tmp->hlptxt=(char *)realloc(tmp->hlptxt,tmp->hlpbsz+bfl+1024); else tmp->hlptxt=(char *)malloc(bfl+1024), tmp->hlptxt[0]=0; tmp->hlpbsz+=bfl+1024; } zcpy(tmp->hlptxt+tmp->hlpsiz,buf); tmp->hlpsiz+=bfl; ++tmp->hlplns; goto up; } break; case ':': /* Select context */ { int x, c; for(x=1;!cwhitef(buf[x]);++x); c=buf[x]; buf[x]=0; if(x!=1) if(!zcmp(buf+1,"def")) { int y; for(buf[x]=c;cwhite(buf[x]);++x); for(y=x;!cwhitef(buf[y]);++y); c=buf[y]; buf[y]=0; if(y!=x) { int sta; MACRO *m; if(cwhite(c) && (m=mparse(NULL,buf+y+1,&sta))) addcmd(buf+x,m); else { err=1; fprintf(stderr,"\n%s %d: macro missing from :def",name,line); } } else { err=1; fprintf(stderr,"\n%s %d: command name missing from :def",name,line); } } else if(!zcmp(buf+1,"inherit")) if(context) { for(buf[x]=c;cwhite(buf[x]);++x); for(c=x;!cwhitef(buf[c]);++c); buf[c]=0; if(c!=x) kcpy(context,getcontext(buf+x)); else { err=1; fprintf(stderr,"\n%s %d: context name missing from :inherit",name,line); } } else { err=1; fprintf(stderr,"\n%s %d: No context selected for :inherit",name,line); } else if(!zcmp(buf+1,"include")) { for(buf[x]=c;cwhite(buf[x]);++x); for(c=x;!cwhitef(buf[c]);++c); buf[c]=0; if(c!=x) { switch(procrc(buf+x)) { case 1: err=1; break; case -1: fprintf(stderr,"\n%s %d: Couldn't open %s",name,line,buf+x); err=1; break; } context=0; o=0; } else { err=1; fprintf(stderr,"\n%s %d: :include missing file name",name,line); } } else if(!zcmp(buf+1,"delete")) if(context) { int y; for(buf[x]=c;cwhite(buf[x]);++x); for(y=x;buf[y]!=0 && buf[y]!='\t' && buf[y]!='\n' && (buf[y]!=' ' || buf[y+1]!=' ');++y); buf[y]=0; kdel(context,buf+x); } else { err=1; fprintf(stderr,"\n%s %d: No context selected for :delete",name,line); } else context=getcontext(buf+1); else { err=1; fprintf(stderr,"\n%s %d: Invalid context name",name,line); } } break; default: /* Get key-sequence to macro binding */ { int x, y, c; MACRO *m; if(!context) { err=1; fprintf(stderr,"\n%s %d: No context selected for macro to key-sequence binding",name,line); break; } m=0; macroloop: m=mparse(m,buf,&x); if(x== -1) { err=1; fprintf(stderr,"\n%s %d: Unknown command in macro",name,line); break; } else if(x== -2) { fgets(buf,1024,fd); goto macroloop; } if(!m) break; /* Skip to end of key sequence */ for(y=x;buf[y]!=0 && buf[y]!='\t' && buf[y]!='\n' && (buf[y]!=' ' || buf[y+1]!=' ');++y); buf[y]=0; /* Add binding to context */ if(kadd(cap,context,buf+x,m)== -1) { fprintf(stderr,"\n%s %d: Bad key sequence '%s'",name,line,buf+x); err=1; } } break; } fclose(fd); /* Close rc file */ /* Print proper ending string */ if(err) fprintf(stderr,"\ndone\n"); else fprintf(stderr,"done\n"); return err; /* 0 for success, 1 for syntax error */ } void izhelp() { struct help *tmp; /* Convert list of help screens into an array */ if(nhelp) { help_structs=(struct help **) malloc(sizeof(struct help *)*(nhelp+1)); help_structs[nhelp]=0; tmp=first_help; while(nhelp--) { help_structs[nhelp]=tmp; tmp=tmp->next; } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.