void read_skel(char *name) { char buf[256]; int section = -2; int line = 0, sline = 1, eline = 1; int i; FILE *fp; if (!(fp = fopen(name, "r"))) open_error(name); while(fgets(buf, 255, fp)) { if ((sline = eline)) line++; if ((i = strlen(buf)) == 0) continue; if (buf[i-1] == '\n') { buf[--i] = 0; eline = 1; } else { buf[i++] = '\\'; buf[i] = 0; eline = 0; } if (sline && buf[0] == '%' && buf[1] == '%') { char *p = buf+2; if (section >= 0) { section_list[section].ptr = fin_section(); } section = -1; while(*p && isspace(*p)) p++; if (isalpha(*p)) { char *e = p; while(isalnum(*++e)); *e = 0; for (i=0; section_list[i].name; i++) if (!strcmp(section_list[i].name, p)) section = i; } if (section >= 0) add_fmt("#line %d \"%s\"", line+1, name); else if (*p) error(0, buf, p, "line %d of \"%s\", bad section name", line, name); } else if (section >= 0) { add_string(buf); } } if (section >= 0) section_list[section].ptr = fin_section(); if (section == -2) error(0, 0, 0, "No sections found in skeleton file \"%s\"", name); }
/* takes format string, returns resizeable array with info about broken up pieces of the format string */ static FmtArray* parse_fmt(const char *fmt) { FmtArray *f=FmtArray_new(10); const char *i,*k; for(i=fmt; i && *i; i=k) { k=strchr(i,'%'); if(k!=i) f=FmtArray_add(f,FmtInfo_new(0,0,0,0,0,substring(i,k))); if(k) f=add_fmt(f,k,&k); } return f; }
const char *get_lesson(void) /* Ask user for desired lesson */ { static StrType response; int ch, n, i, item; struct Lesson *p; char *lp; if (LastLesson) { ch = LastLesson; n = (LastNum == FINISHED)? 1: (LastNum + 1); }else { ch = typeLessons[0].nam; n = 1; } move_cursor(0, 0); #ifdef JPN add_str(" 以下からコースを選択して下さい:"); item = 0; for (p = typeLessons; p->item; p++) { move_cursor(++item, 0); add_fmt(" %s (%c1 - %c%d) ", p->item, p->nam, p->nam, p->num); if (p->fin >= p->num) add_str(" !!!終了!!!"); else if (p->fin > 0) add_fmt(" [%c%dまで終了]", p->nam, p->fin); } move_cursor(++item, 0); add_fmt(" 練習したいレッスンの名前(例 %c%d)を入力して下さい", ch, n); if (HasHelp) { move_cursor(item+1, 0); add_str(" (終了=改行、ヘルプ=?) ------> "); }else add_str(" (終了=改行): "); #else add_str(" Several lessons are available:"); item = 1; for (p = typeLessons; p->item; p++) { move_cursor(item++, 8); add_fmt("%s (%c1 - %c%d) ", p->item, p->nam, p->nam, p->num); if (p->fin >= p->num) add_str(" !!!Finish!!!"); else if (p->fin > 0) add_fmt(" [%c%d was done]", p->nam, p->fin); } move_cursor(++item, 0); add_fmt(" Type the desired lesson name(e.g. %c%d).", ch, n); move_cursor(item+1, 0); add_str(" (Quit=RETURN) ------------> "); #endif cbreak_mode(0); (void)fgets(response, STR_SIZE, stdin); /* avoid gets() */ cbreak_mode(1); for (i = 0; i < STR_SIZE && response[i] != '\n' && response[i] != '\r'; i++) ; response[i] = 0; for (lp = response; *lp == ' ' || *lp == '\t'; lp++) ; if (*lp == 0) cleanup(0); /* EXIT */ if (HasHelp && *lp == '?') return "?1"; /* HELP FILE */ return lp; }
BoolType find_lesson(const char *name) /* locate given lesson, leave lesson_file open so next line begins */ { StrType fullName; StrType current_line; char slash; FILEsIO *lesson_file; size_t linesInLesson; int idx, lng, kind; if ((idx = check_lesson_name(name)) < 0) { stand_out(BOLD); #ifdef JPN add_fmt("\n \"%s\" というレッスンはありません.\n", name); #else add_fmt("\n %s: No such Lesson.\n", name); #endif stand_end(BOLD); (void) wait_user(); return FALSE; } /* gf: Added LessonDir */ slash = isHttp ? '/' : DELIM; if (typeLessons[idx].path == NULL) sprintf(fullName, "%s%c%c.typ", LessonDir, slash, name[0]); else sprintf(fullName, "%s%c%s.typ", LessonDir, slash, typeLessons[idx].path); lesson_file = isHttp ? open_url(fullName) : makeFilesio( fopen(fullName, "r") ); if (lesson_file == NULL) { stand_out(BOLD); add_fmt("OPEN ERROR: %s (errno=%d)\n", fullName, errno); stand_end(BOLD); (void) wait_user(); return FALSE; } if (!seek_lesson(lesson_file, name)) goto ERR_EXIT; /* clear previous lesson */ clear_dictionary(); clear_cache(); linesInLesson = 0; while ((lng = get_lesson_line(lesson_file, current_line)) >= 0) { /* Loop ends if EOF or End of Lesson */ kind = 0; if (lng >= 2 && current_line[lng - 2] == '\\') { /* expected terminator */ kind = current_line[lng - 1]; current_line[lng -= 2] = '\0'; /* remove */ } if (lng == 0) cached_lines[linesInLesson] = empty; else { char *pp = (char *)malloc(lng + 1); if (pp == NULL) { fprintf(stderr, "SYSTEM ERROR: malloc() failure\n"); cleanup(1); } strcpy(pp, current_line); cached_lines[linesInLesson] = pp; } cached_attr[linesInLesson] = kind; if (++linesInLesson >= cacheCapacity - 1) increse_cache(); } /* The next of the last line, cached_lines[linesInLesson] should be NULL */ ioclose(lesson_file); return TRUE; ERR_EXIT: stand_out(BOLD); #ifdef JPN add_fmt("レッスン%s は利用できません.\n", &name[1]); #else add_fmt("Lesson %s is not available.\n", &name[1]); #endif stand_end(BOLD); (void) wait_user(); ioclose(lesson_file); return FALSE; }
static char * sial_ptr(char *fmt, value_t **vals) { /* We need to ensure that we dont overflow our string buffer. Although its unlikely we will overflow it with just numbers, strings will easliy overflow. So, lets check for strings and see how long they are. */ int len=0; char *nfmt=NULL,*ni=NULL; char *onefmt=NULL, *onei=NULL; char *p=fmt; char last=' '; int curarg=0; #define NBYTES (len-(nfmt-ni)) int i = 0; while(vals[i] != NULL) { if(vals[i]->type.type == V_STRING) len+=vals[i]->type.size; i++; } /* We add a fudge factor of 100, which should cover all the number arguments */ len+=strlen(fmt) + 100; nfmt=sial_alloc(len); ni=nfmt; onefmt=sial_alloc(len); onei=onefmt; while(*p) { if(*p=='%') { static regex_t preg; static int done=0; regmatch_t matches[NMATCH]; if(!done) { regcomp(&preg, FMTREG, REG_EXTENDED); done=1; } /* build a new format translation */ onefmt=onei; *onefmt++=*p++; /* if the returned pointer is (char*)-1 or NULL then something is wrong */ if(!regexec(&preg, p, NMATCH, matches, 0)) { int i, n=matches[0].rm_eo-1; int posarg, wpos, ppos; char *pi=p; /* save p for ptrto() macro */ /* check that the width and precision field args point to a int value_t. If they were used */ wpos=chkforint(ptrto(M_WIDTHARG), vals, &curarg); ppos=chkforint(ptrto(M_PRECARG), vals, &curarg); /* argument position was specfified ? */ if(ptrto(M_POSP)) { /* we work from 0-n, printf works from 1-n */ if(sscanf(ptrto(M_POSP), "%d", &posarg)==1) posarg--; if(posarg >= BT_MAXARGS || !vals[posarg]) { sial_error("Invalid arg position specified [%d]", posarg+1); } } else posarg=curarg++; /* jump over the format spec in the original */ p+=n; #if 0 for(i=0;i<NMATCH;i++) { char buf[40]; if(ptrto(i)) { int n=matchlen(i); strncpy(buf, pi+matches[i].rm_so, n); buf[n]='\0'; printf("match[%d]=[%s]\n", i, buf); } } #endif /* copy all format specs to destination except fmt */ for(i=0;i<sizeof(addit)/sizeof(addit[0]);i++) { switch(addit[i]) { case M_WIDTHARG: if(wpos >=0 ){ *onefmt++='*'; } else goto def; break; case M_PRECARG: if(ppos >=0 ){ *onefmt++='.'; *onefmt++='*'; } else goto def; break; case M_PREC: if(ptrto(addit[i])) *onefmt++='.'; goto def; default: def: if(ptrto(addit[i])) { strcpy(onefmt, ptrto(addit[i])); onefmt+=matchlen(addit[i]); } } } if(*p=='p') { ref: /* if user overrides anything don't do nothing */ if(ptrto(M_FLAGS)||ptrto(M_WIDTH)||ptrto(M_WIDTHARG)||ptrto(M_PREC)||ptrto(M_PRECARG)||ptrto(M_SIZE)) { *onefmt++='p'; } else { if(sial_defbsize()==8) { strcpy(onefmt, "016llx"); onefmt+=6; } else { strcpy(onefmt, "08x"); onefmt+=3; } } *onefmt='\0'; p++; nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals); } else if(*p=='>') { nfmt--; if(sial_defbsize()==8) { int i; for(i=0;i<8;i++) *nfmt++=last; } p++; curarg--; } else if(*p=='?') { /* put the proper format for the user */ if(!vals[posarg]) { sial_error("Expected additional argument %d\n", posarg+1); } else switch(vals[posarg]->type.type) { case V_BASE: case V_ENUM: { if(!ptrto(M_SIZE)) { if(vals[posarg]->type.size==8) { *onefmt++='l'; *onefmt++='l'; } } if(sial_issigned(vals[posarg]->type.typattr)) { *onefmt++='d'; }else{ *onefmt++='u'; } } break; case V_REF: { *p='p'; goto ref; } case V_STRING: { *onefmt++='s'; } break; } p++; *onefmt='\0'; nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals); } else { /* check that format and value_t agree */ /* can't do a lot more then check for strings vs anything_else */ if(!vals[posarg]) { sial_error("Expected additional argument %d\n", posarg+1); } else if(*p=='s') { if(vals[posarg]->type.type != V_STRING) { sial_error("Expected type 'string' as arg%d", posarg+1); } } else if(vals[posarg]->type.type == V_STRING) { sial_error("Incompatible type 'string' in arg%d", posarg+1); } *onefmt++=*p++; *onefmt='\0'; nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals); } } else { sial_warning("Malformed format specifier!"); } } else { last=*p; if(nfmt-ni > len) sial_error("format tranlation overflow!"); *nfmt++=*p++; } } sial_free(onei); *nfmt='\0'; return ni; }