static struct tm * parse_date2(const char *str) { /* Thu, 10 Jan 1993 01:29:59 GMT */ const char *s; static struct tm tm; assert(NULL != str); memset(&tm, '\0', sizeof(struct tm)); s = strchr(str, ','); if (NULL == s) return NULL; s++; while (*s == ' ') s++; /* backup if month is only one digit */ if (xisdigit(*s) && !xisdigit(*(s + 1))) s--; if (strchr(s, '-')) return NULL; if ((int) strlen(s) < 20) return NULL; memset(&tm, '\0', sizeof(tm)); tm.tm_mday = make_num(s); tm.tm_mon = make_month(s + 3); tm.tm_year = (100 * make_num(s + 7) - 1900) + make_num(s + 9); tm.tm_hour = make_num(s + 12); tm.tm_min = make_num(s + 15); tm.tm_sec = make_num(s + 18); return tmSaneValues(&tm) ? &tm : NULL; }
void #line 366 "./cwebdir/ctang-w2c.ch" skip_limbo P1H(void) #line 1481 "./cwebdir/ctangle.w" { char c; while(1){ if(loc> limit&&get_line()==0)return; *(limit+1)= '@'; while(*loc!='@')loc++; if(loc++<=limit){ c= *loc++; if(ccode[(eight_bits)c]==new_section)break; switch(ccode[(eight_bits)c]){ case translit_code:/*93:*/ #line 1507 "./cwebdir/ctangle.w" while(xisspace(*loc)&&loc<limit)loc++; loc+= 3; if(loc> limit||!xisxdigit(*(loc-3))||!xisxdigit(*(loc-2)) ||(*(loc-3)>='0'&&*(loc-3)<='7')||!xisspace(*(loc-1))) err_print("! Improper hex number following @l"); else{ unsigned i; char*beg; sscanf(loc-3,"%x",&i); while(xisspace(*loc)&&loc<limit)loc++; beg= loc; while(loc<limit&&(xisalpha(*loc)||xisdigit(*loc)||*loc=='_'))loc++; if(loc-beg>=translit_length) err_print("! Replacement string in @l too long"); else{ strncpy(translit[i-0200],beg,loc-beg); translit[i-0200][loc-beg]= '\0'; } } /*:93*/ #line 1491 "./cwebdir/ctangle.w" ;break; case format_code:case'@':break; case control_text:if(c=='q'||c=='Q'){ while((c= skip_ahead())=='@'); if(*(loc-1)!='>') err_print("! Double @ should be used in control text"); break; } default:err_print("! Double @ should be used in limbo"); } } } }
/* * parses an int field, complains if soemthing went wrong, returns true on * success */ int httpHeaderParseInt(const char *start, int *value) { assert(value); *value = atoi(start); if (!*value && !xisdigit(*start)) { debug(66, 2) ("failed to parse an int header field near '%s'\n", start); return 0; } return 1; }
/* assume ascii */ static inline int dpkgEVRctype(char x) /*@*/ { int c = (int)x; return ( x == '~' ? -1 : xisdigit(c) ? 0 : x == '\0' ? 0 \ : xisalpha(c) ? c : c + 256 ); }
int dpkgEVRcmp(const char *a, const char *b) { if (a == NULL) a = ""; if (b == NULL) b = ""; while (*a || *b) { int first_diff= 0; while ( (*a && !xisdigit((int)*a)) || (*b && !xisdigit((int)*b)) ) { int vc = dpkgEVRctype(*a); int rc = dpkgEVRctype(*b); if (vc != rc) return vc - rc; a++; b++; } while (*a == '0') a++; while (*b == '0') b++; while (xisdigit((int)*a) && xisdigit((int)*b)) { if (!first_diff) first_diff = (int)(*a - *b); a++; b++; } if (xisdigit((int)*a)) return 1; if (xisdigit((int)*b)) return -1; if (first_diff) return first_diff; } return 0; }
nsType rpmnsClassify(const char * s, size_t slen) { const char * se; nsType Type; if (slen == 0) slen = strlen(s); if (*s == '!') { s++; slen--; } if (*s == '/') return RPMNS_TYPE_PATH; se = s + slen; if (s[0] == '%' && s[1] == '{' && se[-1] == '}') return RPMNS_TYPE_FUNCTION; if ((se - s) > 3 && se[-3] == '.' && se[-2] == 's' && se[-1] == 'o') return RPMNS_TYPE_DSO; Type = rpmnsProbe(s, slen); if (Type != RPMNS_TYPE_UNKNOWN) return Type; for (se = s; *se != '\0'; se++) { if (se[0] == '(' || se[--slen] == ')') return RPMNS_TYPE_NAMESPACE; if (se[0] == '.' && se[1] == 's' && se[2] == 'o') return RPMNS_TYPE_DSO; if (se[0] == '.' && xisdigit((int)se[-1]) && xisdigit((int)se[1])) return RPMNS_TYPE_VERSION; if (_rpmns_N_at_A && _rpmns_N_at_A[0]) { if (se[0] == _rpmns_N_at_A[0] && rpmnsArch(se+1)) return RPMNS_TYPE_ARCH; } /*@-globstate@*/ if (se[0] == '.') return RPMNS_TYPE_COMPOUND; } return RPMNS_TYPE_STRING; /*@=globstate@*/ }
static struct tm * parse_date1(const char *str) { /* Thursday, 10-Jun-93 01:29:59 GMT */ const char *s; static struct tm tm; assert(NULL != str); memset(&tm, '\0', sizeof(struct tm)); s = strchr(str, ','); if (NULL == s) return NULL; s++; while (*s == ' ') s++; /* backup if month is only one digit */ if (xisdigit(*s) && !xisdigit(*(s + 1))) s--; if (!strchr(s, '-')) return NULL; if ((int) strlen(s) < 18) return NULL; memset(&tm, '\0', sizeof(tm)); tm.tm_mday = make_num(s); tm.tm_mon = make_month(s + 3); tm.tm_year = make_num(s + 7); /* * Y2K: Arjan de Vet <*****@*****.**> * if tm.tm_year < 70, assume it's after the year 2000. */ if (tm.tm_year < 70) tm.tm_year += 100; tm.tm_hour = make_num(s + 10); tm.tm_min = make_num(s + 13); tm.tm_sec = make_num(s + 16); return tmSaneValues(&tm) ? &tm : NULL; }
/* returns http status extracted from status line or -1 on parsing failure */ static int parse_status_line(const char *sline, const char **statusStr) { const char *sp = strchr(sline, ' '); if (statusStr) *statusStr = NULL; if (strncasecmp(sline, "HTTP/", 5) || !sp) return -1; while (xisspace(*++sp)); if (!xisdigit(*sp)) return -1; if (statusStr) *statusStr = sp; return atoi(sp); }
static void split_num(Vstr_sects *sects, Vstr_base *s2, size_t pos, size_t len) { Vstr_iter iter[1]; if (!vstr_iter_fwd_beg(s2, pos, len, iter)) err(EXIT_FAILURE, "INTERNAL ERROR"); while (len--) { char chr = vstr_iter_fwd_chr(iter, NULL); if (xisdigit(chr)) vstr_sects_add(sects, pos, 1); ++pos; } }
/* pack fields using Packer */ int httpStatusLineParse(HttpStatusLine * sline, const char *start, const char *end) { assert(sline); sline->status = HTTP_INVALID_HEADER; /* Squid header parsing error */ if (strncasecmp(start, "HTTP/", 5)) return 0; start += 5; if (!xisdigit(*start)) return 0; sline->version = atof(start); if (!(start = strchr(start, ' '))) return 0; sline->status = atoi(++start); /* we ignore 'reason-phrase' */ return 1; /* success */ }
/* This routine should be rewritten to not require copying the buffer - [ahc] */ static struct tm * parse_date(const char *str, int len) { struct tm *tm; char tmp[TIMEBUFLEN]; char *t; char *wday = NULL; char *day = NULL; char *month = NULL; char *year = NULL; char *time = NULL; char *zone = NULL; int bl = MIN(len, TIMEBUFLEN - 1); memcpy(tmp, str, bl); tmp[bl] = '\0'; for (t = strtok(tmp, ", "); t; t = strtok(NULL, ", ")) { if (xisdigit(*t)) { if (!day) { day = t; t = strchr(t, '-'); if (t) { *t++ = '\0'; month = t; t = strchr(t, '-'); if (!t) return NULL; *t++ = '\0'; year = t; } } else if (strchr(t, ':')) time = t; else if (!year) year = t; } else if (!wday) wday = t; else if (!month) month = t; else if (!zone) zone = t; } tm = parse_date_elements(day, month, year, time, zone); return tm; }
static struct tm * parse_date(const char *str) { struct tm *tm; char *tmp = xstrdup(str); char *t; char *wday = NULL; char *day = NULL; char *month = NULL; char *year = NULL; char *time = NULL; char *zone = NULL; for (t = strtok(tmp, ", "); t; t = strtok(NULL, ", ")) { if (xisdigit(*t)) { if (!day) { day = t; t = strchr(t, '-'); if (t) { *t++ = '\0'; month = t; t = strchr(t, '-'); if (!t) return NULL; *t++ = '\0'; year = t; } } else if (strchr(t, ':')) time = t; else if (!year) year = t; } else if (!wday) wday = t; else if (!month) month = t; else if (!zone) zone = t; } tm = parse_date_elements(day, month, year, time, zone); xfree(tmp); return tm; }
/* pack fields using Packer */ int httpStatusLineParse(HttpStatusLine * sline, const char *start, const char *end) { assert(sline); sline->status = HTTP_INVALID_HEADER; /* Squid header parsing error */ if (strncasecmp(start, "HTTP/", 5)) return 0; start += 5; if (!xisdigit(*start)) return 0; if (sscanf(start, "%d.%d", &sline->version.major, &sline->version.minor) != 2) { debug(57, 7) ("httpStatusLineParse: Invalid HTTP identifier.\n"); } if (!(start = strchr(start, ' '))) return 0; sline->status = (http_status) atoi(++start); /* we ignore 'reason-phrase' */ return 1; /* success */ }
static int prnt_phone_name(Vstr_base *s1, Vstr_base *s2, size_t pos, size_t len, Vstr_sects *sects, unsigned int off) { size_t cpos = 0; char chr = 0; char nxt_chr = 0; if (off > sects->num) return (FALSE); cpos = VSTR_SECTS_NUM(sects, off)->pos; chr = vstr_export_chr(s2, cpos); nxt_chr = phone_state[(unsigned char) chr]; vstr_sub_rep_chr(s2, cpos, 1, nxt_chr, 1); if (xisdigit(nxt_chr)) { if (!prnt_phone_name(s1, s2, pos, len, sects, off + 1)) return (FALSE); } return (TRUE); }
int if_err_(int argc, char **argv) { char *interface; size_t interface_len; FILE *f; char buff[256], *s; int i; interface = basename(argv[0]); if(strncmp(interface, "if_err_", 7) != 0) return fail("if_err_ invoked with invalid basename"); interface += 7; interface_len = strlen(interface); if(argc > 1) { if(!strcmp(argv[1], "autoconf")) return autoconf_check_readable(PROC_NET_DEV); if(!strcmp(argv[1], "suggest")) { if(NULL == (f = fopen(PROC_NET_DEV, "r"))) return 1; while(fgets(buff, 256, f)) { for(s=buff;*s == ' ';++s) ; i = 0; if(!strncmp(s, "lo:", 3)) continue; if(!strncmp(s, "sit", 3)) { for(i=3; xisdigit(s[i]); ++i) ; if(s[i] == ':') continue; } while(s[i] != ':' && s[i] != '\0') ++i; if(s[i] != ':') continue; /* a header line */ s[i] = '\0'; puts(s); } fclose(f); return 0; } if(!strcmp(argv[1], "config")) { puts("graph_order rcvd trans"); printf("graph_title %s errors\n", interface); puts("graph_args --base 1000\n" "graph_vlabel packets in (-) / out (+) per " "${graph_period}\n" "graph_category network"); printf("graph_info This graph shows the amount of " "errors on the %s network interface.\n", interface); puts("rcvd.label packets\n" "rcvd.type COUNTER\n" "rcvd.graph no\n" "rcvd.warning 1\n" "trans.label packets\n" "trans.type COUNTER\n" "trans.negative rcvd\n" "trans.warning 1"); print_warncrit("rcvd"); print_warncrit("trans"); return 0; } } if(NULL == (f = fopen(PROC_NET_DEV, "r"))) return 1; while(fgets(buff, 256, f)) { for(s=buff;*s == ' ';++s) ; if(0 != strncmp(s, interface, interface_len)) continue; s += interface_len; if(*s != ':') continue; ++s; while(*s == ' ') ++s; for(i=1;i<3;++i) { while(xisdigit(*s)) ++s; while(xisspace(*s)) ++s; } for(i=0;xisdigit(s[i]);++i) ; printf("rcvd.value "); fwrite(s, 1, i, stdout); putchar('\n'); s += i; while(xisspace(*s)) ++s; for(i=4;i<11;++i) { while(xisdigit(*s)) ++s; while(xisspace(*s)) ++s; } for(i=0;xisdigit(s[i]);++i) ; printf("trans.value "); fwrite(s, 1, i, stdout); putchar('\n'); } fclose(f); return 0; }
int cpu(int argc, char **argv) { FILE *f; char buff[256]; int ncpu = 0, extinfo = 0, ret; bool scaleto100 = false; if (argc > 1) { if (!strcmp(argv[1], "config")) { char *s = getenv("scaleto100"); if (s && !strcmp(s, "yes")) scaleto100 = true; if (!(f = fopen(PROC_STAT, "r"))) return fail("cannot open " PROC_STAT); while (fgets(buff, 256, f)) { if (!strncmp(buff, "cpu", 3)) { if (xisdigit(buff[3])) ncpu++; if (buff[3] == ' ' && 0 == extinfo) { strtok(buff + 4, " \t"); for (extinfo = 1; strtok(NULL, " \t"); extinfo++); } } } fclose(f); if (ncpu < 1 || extinfo < 4) return fail("cannot parse " PROC_STAT); puts("graph_title CPU usage"); if (extinfo >= 7) puts("graph_order system user nice idle iowait irq softirq"); else puts("graph_order system user nice idle"); if (scaleto100) puts("graph_args --base 1000 -r --lower-limit 0 --upper-limit 100"); else printf ("graph_args --base 1000 -r --lower-limit 0 --upper-limit %d\n", 110 * ncpu); puts("graph_vlabel %\n" "graph_scale no\n" "graph_info This graph shows how CPU time is spent.\n" "graph_category system\n" "graph_period second\n" "system.label system\n" "system.draw AREA"); printf("system.max %d\n", 110 * ncpu); puts("system.min 0\n" "system.type DERIVE"); printf("system.warning %d\n", SYSWARNING * ncpu); printf("system.critical %d\n", SYSCRITICAL * ncpu); puts("system.info CPU time spent by the kernel in system activities\n" "user.label user\n" "user.draw STACK\n" "user.min 0"); printf("user.max %d\n", 110 * ncpu); printf("user.warning %d\n", USRWARNING * ncpu); puts("user.type DERIVE\n" "user.info CPU time spent by normal programs and daemons\n" "nice.label nice\n" "nice.draw STACK\n" "nice.min 0"); printf("nice.max %d\n", 110 * ncpu); puts("nice.type DERIVE\n" "nice.info CPU time spent by nice(1)d programs\n" "idle.label idle\n" "idle.draw STACK\n" "idle.min 0"); printf("idle.max %d\n", 110 * ncpu); puts("idle.type DERIVE\n" "idle.info Idle CPU time"); if (scaleto100) printf("system.cdef system,%d,/\n" "user.cdef user,%d,/\n" "nice.cdef nice,%d,/\n" "idle.cdef idle,%d,/\n", ncpu, ncpu, ncpu, ncpu); if (extinfo >= 7) { puts("iowait.label iowait\n" "iowait.draw STACK\n" "iowait.min 0"); printf("iowait.max %d\n", 110 * ncpu); puts("iowait.type DERIVE\n" "iowait.info CPU time spent waiting for I/O operations to finish\n" "irq.label irq\n" "irq.draw STACK\n" "irq.min 0"); printf("irq.max %d\n", 110 * ncpu); puts("irq.type DERIVE\n" "irq.info CPU time spent handling interrupts\n" "softirq.label softirq\n" "softirq.draw STACK\n" "softirq.min 0"); printf("softirq.max %d\n", 110 * ncpu); puts("softirq.type DERIVE\n" "softirq.info CPU time spent handling \"batched\" interrupts"); if (scaleto100) printf("iowait.cdef iowait,%d,/\n" "irq.cdef irq,%d,/\n" "softirq.cdef softirq,%d,/\n", ncpu, ncpu, ncpu); } if (extinfo >= 8) { puts("steal.label steal\n" "steal.draw STACK\n" "steal.min 0"); printf("steal.max %d\n", 110 * ncpu); puts("steal.type DERIVE\n" "steal.info The time that a virtual CPU had runnable tasks, but the virtual CPU itself was not running"); if (scaleto100) printf("steal.cdef steal,%d,/\n", ncpu); } if (extinfo >= 9) { puts("guest.label guest\n" "guest.draw STACK\n" "guest.min 0"); printf("guest.max %d\n", 110 * ncpu); puts("guest.type DERIVE\n" "guest.info The time spent running a virtual CPU for guest operating systems under the control of the Linux kernel."); if (scaleto100) printf("guest.cdef guest,%d,/\n", ncpu); } return 0; } if (!strcmp(argv[1], "autoconf")) return autoconf_check_readable(PROC_STAT); } if (!(f = fopen(PROC_STAT, "r"))) return fail("cannot open " PROC_STAT); while (fgets(buff, 256, f)) { if (!strncmp(buff, "cpu ", 4)) { ret = parse_cpu_line(buff); goto OK; } } /* We didn't find anyting */ ret = fail("no cpu line found in " PROC_STAT); OK: fclose(f); return ret; }
/* ** The root program. All variations call this core. ** ** INPUTS: ** func This is a pointer to a function taking three arguments ** 1. A pointer to the list of characters to be output ** (Note, this list is NOT null terminated.) ** 2. An integer number of characters to be output. ** (Note: This number might be zero.) ** 3. A pointer to anything. Same as the "arg" parameter. ** ** arg This is the pointer to anything which will be passed as the ** third argument to "func". Use it for whatever you like. ** ** fmt This is the format string, as in the usual printf. ** ** ap This is a pointer to a list of arguments. Same as in ** vfprintf. ** ** OUTPUTS: ** The return value is the total number of characters sent to ** the function "func". Returns EOF on a error. ** ** Note that the order in which automatic variables are declared below ** seems to make a big difference in determining how fast this beast ** will run. */ static Int32 vxprintf(void (*func)(char*,Int32,void*), void *arg, const char *format, va_list ap){ register const char *fmt; /* The format string. */ register Int32 c; /* Next character in the format string */ register char *bufpt; /* Pointer to the conversion buffer */ register Int32 precision; /* Precision of the current field */ register Int32 length; /* Length of the field */ register Int32 idx; /* A general purpose loop counter */ Int32 count; /* Total number of characters output */ Int32 width; /* Width of the current field */ Int32 flag_leftjustify; /* True if "-" flag is present */ Int32 flag_plussign; /* True if "+" flag is present */ Int32 flag_blanksign; /* True if " " flag is present */ Int32 flag_alternateform; /* True if "#" flag is present */ Int32 flag_zeropad; /* True if field width constant starts with zero */ UInt32 longvalue; /* Value for integer types */ Float32 realvalue; /* Value for real types */ const info *infop; /* Pointer to the appropriate info structure */ char buf[BUFSIZE]; /* Conversion buffer */ char prefix; /* Prefix character. "+" or "-" or " " or 0. */ Int32 errorflag = 0; /* True if an error is encountered */ enum e_type xtype; /* Which of 3 different FP formats */ static char spaces[]=" "; #define SPACESIZE (sizeof(spaces)-1) Int32 exp; /* exponent of real numbers */ Float32 rounder; /* Used for rounding floating point values */ Int32 flag_dp; /* True if decimal point should be shown */ Int32 flag_rtz; /* True if trailing zeros should be removed */ fmt = format; /* Put in a register for speed */ count = length = 0; bufpt = 0; for(; (c=(*fmt))!=0; ++fmt){ if( c!='%' ){ register Int32 amt; bufpt = (char *)fmt; amt = 1; while( (c=*++fmt)!='%' && c!=0 ) amt++; (*func)(bufpt,amt,arg); count += amt; if( c==0 ) break; } if( (c=(*++fmt))==0 ){ errorflag = 1; (*func)("%",1,arg); count++; break; } /* Find out what flags are present */ flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_zeropad = 0; do{ switch( c ){ case '-': flag_leftjustify = 1; c = 0; break; case '+': flag_plussign = 1; c = 0; break; case ' ': flag_blanksign = 1; c = 0; break; case '#': flag_alternateform = 1; c = 0; break; case '0': flag_zeropad = 1; c = 0; break; default: break; } }while( c==0 && (c=*++fmt)!=0 ); /* Get the field width */ width = 0; if( c=='*' ){ width = va_arg(ap,Int32); if( width<0 ){ flag_leftjustify = 1; width = -width; } c = *++fmt; }else{ while( xisdigit(c) ){ width = width*10 + c - '0'; c = *++fmt; } } /* Get the precision */ if( c=='.' ){ precision = 0; c = *++fmt; if( c=='*' ){ precision = va_arg(ap,Int32); if( precision<0 ) precision = -precision; c = *++fmt; }else{ while( xisdigit(c) ){ precision = precision*10 + c - '0'; c = *++fmt; } } /* Limit the precision to prevent overflowing buf[] during conversion */ if( precision>BUFSIZE-40 ) precision = BUFSIZE-40; }else{ precision = -1; } /* Fetch the info entry for the field */ infop = 0; for(idx=0; idx<NINFO; idx++){ if( c==fmtinfo[idx].fmttype ){ infop = &fmtinfo[idx]; break; } } /* No info entry found. it must be an error. Check it out. */ if( infop==0 ){ xtype = IOERROR; }else{ xtype = infop->type; } /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. ** flag_plussign TRUE if a '+' is present. ** flag_leftjustify TRUE if a '-' is present or if the ** field width was negative. ** flag_zeropad TRUE if the width began with 0. ** flag_blanksign TRUE if a ' ' is present. ** width The specified field width. This is ** always non-negative. Zero is the default. ** precision The specified precision. The default ** is -1. ** xtype The class of the conversion. ** infop Pointer to the appropriate info struct. */ switch( xtype ){ case RADIX: longvalue = va_arg(ap,Int32); /* More sensible: turn off the prefix for octal (to prevent "00"), ** but leave the prefix for hex. */ if( longvalue==0 && infop->base==8 ) flag_alternateform = 0; if( infop->flag_signed ){ if( *(Int32*)&longvalue<0 ){ longvalue = -*(Int32*)&longvalue; prefix = '-'; }else if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; }else prefix = 0; if( flag_zeropad && precision<width-(prefix!=0) ){ precision = width-(prefix!=0); } { register char *cset; /* Use registers for speed */ register Int32 base; cset = infop->charset; base = infop->base; bufpt = &buf[BUFSIZE]; do{ /* Convert to ascii */ *(--bufpt) = cset[longvalue%base]; longvalue = longvalue/base; }while( longvalue>0 ); } length = (Int32)&buf[BUFSIZE]-(Int32)bufpt; for(idx=precision-length; idx>0; idx--){ *(--bufpt) = '0'; /* Zero pad */ } if( prefix ) *(--bufpt) = prefix; /* Add sign */ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ char *pre, x; pre = infop->prefix; if( *bufpt!=pre[0] ){ for(pre=infop->prefix; (x=*pre)!=0; pre++) *(--bufpt) = x; } } length = (Int32)&buf[BUFSIZE]-(Int32)bufpt; break; case FLOAT: case EXP: case GENERIC: realvalue = va_arg(ap,Float64); if( precision<0 ) precision = 4; /* Set default precision */ if( precision>BUFSIZE-10 ) precision = BUFSIZE-10; if( realvalue<0.0 ){ realvalue = -realvalue; prefix = '-'; }else{ if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; } if( infop->type==GENERIC && precision>0 ) precision--; for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1); if( infop->type==FLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; while( realvalue>=1e8 ){ realvalue *= 1e-8; exp+=8; } while( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } bufpt = buf; /* ** If the field type is GENERIC, then convert to either EXP ** or FLOAT, as appropriate. */ if( xtype==GENERIC ){ flag_rtz = !flag_alternateform; if( exp<-4 || exp>precision ){ xtype = EXP; }else{ precision = precision - exp; realvalue += rounder; xtype = FLOAT; } } /* ** The "exp+precision" test causes output to be of type EXP if ** the precision is too large to fit in buf[]. */ if( xtype==FLOAT && exp+precision<BUFSIZE-30 ){ flag_rtz = 0; flag_dp = (precision>0 || flag_alternateform); if( prefix ) *(bufpt++) = prefix; /* Sign */ if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */ else for(; exp>=0; exp--) *(bufpt++) = getdigit(&realvalue); if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */ for(exp++; exp<0 && precision>0; precision--, exp++){ *(bufpt++) = '0'; } while( (precision--)>0 ) *(bufpt++) = getdigit(&realvalue); *(bufpt--) = 0; /* Null terminate */ if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; } bufpt++; /* point to next free slot */ }else{ /* EXP */ flag_rtz = 0; flag_dp = (precision>0 || flag_alternateform); realvalue += rounder; if( prefix ) *(bufpt++) = prefix; /* Sign */ *(bufpt++) = getdigit(&realvalue); /* First digit */ if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */ while( (precision--)>0 ) *(bufpt++) = getdigit(&realvalue); bufpt--; /* point to last digit */ if( flag_rtz && flag_dp ){ /* Remove tail zeros */ while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; } bufpt++; /* point to next free slot */ *(bufpt++) = infop->charset[0]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */ else { *(bufpt++) = '+'; } if( exp>=100 ) *(bufpt++) = (exp/100)+'0'; /* 100's digit */ *(bufpt++) = exp/10+'0'; /* 10's digit */ *(bufpt++) = exp%10+'0'; /* 1's digit */ } /* The converted number is in buf[] and zero terminated. Output it. ** Note that the number is in the usual order, not reversed as with ** integer conversions. */ length = (Int32)bufpt-(Int32)buf; bufpt = buf; break; case SIZE: *(va_arg(ap,Int32*)) = count; length = width = 0; break; case PERCENT: buf[0] = '%'; bufpt = buf; length = 1; break; case CHARLIT: case CHAR: c = buf[0] = (xtype==CHAR ? va_arg(ap,Int32) : *++fmt); if( precision>=0 ){ for(idx=1; idx<precision; idx++) buf[idx] = c; length = precision; }else{ length =1; } bufpt = buf; break; case STRING: bufpt = va_arg(ap,char*); if( bufpt==0 ) bufpt = "(null)"; length = xstrlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; case IOERROR: buf[0] = '%'; buf[1] = c; errorflag = 0; idx = 1+(c!=0); (*func)("%",idx,arg); count += idx; if( c==0 ) fmt--; break; }/* End switch over the format type */ /* ** The text of the conversion is pointed to by "bufpt" and is ** "length" characters long. The field width is "width". Do ** the output. */ if( !flag_leftjustify ){ register Int32 nspace; nspace = width-length; if( nspace>0 ){ count += nspace; while( nspace>=SPACESIZE ){ (*func)(spaces,SPACESIZE,arg); nspace -= SPACESIZE; } if( nspace>0 ) (*func)(spaces,nspace,arg); } } if( length>0 ){ (*func)(bufpt,length,arg); count += length; } if( flag_leftjustify ){ register Int32 nspace; nspace = width-length; if( nspace>0 ){ count += nspace; while( nspace>=SPACESIZE ){ (*func)(spaces,SPACESIZE,arg); nspace -= SPACESIZE; } if( nspace>0 ) (*func)(spaces,nspace,arg); } } }/* End for loop over the format string */ return errorflag ? EOF : count; } /* End of function */
/* * Do format conversion placing the output in buffer */ static int format_converter(register buffy * odp, const char *fmt, va_list ap) { register char *sp; register char *bep; register int cc = 0; register int i; register char *s = NULL; char *q; int s_len; register int min_width = 0; int precision = 0; enum { LEFT, RIGHT } adjust; char pad_char; char prefix_char; double fp_num; wide_int i_num = (wide_int) 0; u_wide_int ui_num; char num_buf[NUM_BUF_SIZE]; char char_buf[2]; /* for printing %% and %<unknown> */ /* * Flag variables */ boolean_e is_long; boolean_e alternate_form; boolean_e print_sign; boolean_e print_blank; boolean_e adjust_precision; boolean_e adjust_width; bool_int is_negative; sp = odp->nextb; bep = odp->buf_end; while (*fmt) { if (*fmt != '%') { INS_CHAR(*fmt, sp, bep, cc); } else { /* * Default variable settings */ adjust = RIGHT; alternate_form = print_sign = print_blank = NO; pad_char = ' '; prefix_char = NUL; fmt++; /* * Try to avoid checking for flags, width or precision */ if (xisascii(*fmt) && !xislower(*fmt)) { /* * Recognize flags: -, #, BLANK, + */ for (;; fmt++) { if (*fmt == '-') adjust = LEFT; else if (*fmt == '+') print_sign = YES; else if (*fmt == '#') alternate_form = YES; else if (*fmt == ' ') print_blank = YES; else if (*fmt == '0') pad_char = '0'; else break; } /* * Check if a width was specified */ if (xisdigit(*fmt)) { STR_TO_DEC(fmt, min_width); adjust_width = YES; } else if (*fmt == '*') { min_width = va_arg(ap, int); fmt++; adjust_width = YES; if (min_width < 0) { adjust = LEFT; min_width = -min_width; } } else adjust_width = NO; /* * Check if a precision was specified * * XXX: an unreasonable amount of precision may be specified * resulting in overflow of num_buf. Currently we * ignore this possibility. */ if (*fmt == '.') { adjust_precision = YES; fmt++; if (xisdigit(*fmt)) { STR_TO_DEC(fmt, precision); } else if (*fmt == '*') { precision = va_arg(ap, int); fmt++; if (precision < 0) precision = 0; } else
static void icq_get_user_info(session_t *s, userlist_t *u, struct icq_tlv_list *tlvs, int newstatus) { int caps = 0, desc_chg = 0; char *descr = NULL; icq_tlv_t *t; if (!u) return; debug_function("icq_get_user_info() %s\n", u->uid); descr = u->descr ? xstrdup(u->descr) : NULL; user_private_item_set_int(u, "idle", 0); user_private_item_set_int(u, "status_f", 0); user_private_item_set_int(u, "xstatus", 0); for (t = tlvs; t; t = t->next) { /* Check t->len */ switch (t->type) { case 0x01: if (tlv_length_check("icq_get_user_info()", t, 2)) continue; break; case 0x03: case 0x04: case 0x05: case 0x06: case 0x0a: case 0x0f: if (tlv_length_check("icq_get_user_info()", t, 4)) continue; break; } /* now we've got trusted length */ switch (t->type) { case 0x01: /* User class */ user_private_item_set_int(u, "class", t->nr); break; case 0x03: /* Time when client gone online (unix time_t) */ user_private_item_set_int(u, "online", t->nr); break; case 0x04: /* idle timer */ { uint16_t idle; if ( (idle = t->nr) ) user_private_item_set_int(u, "idle", time(NULL) - 60*idle); break; } case 0x05: /* Time when this account was registered (unix time_t) */ user_private_item_set_int(u, "member", t->nr); break; case 0x06: { /* User status * * ICQ service presence notifications use user status field which consist * of two parts. First is a various flags (birthday flag, webaware flag, * etc). Second is a user status (online, away, busy, etc) flags. */ uint16_t status = t->nr & 0xffff; uint16_t flags = t->nr >> 16; user_private_item_set_int(u, "status_f", flags); debug_white(" %s status flags=0x%04x status=0x%04x\n", u->uid, flags, status); newstatus = icq2ekg_status(status); break; } case 0x0a: /* IP address */ { uint32_t ip; if (icq_unpack_nc(t->buf, t->len, "i", &ip)) { if (ip) user_private_item_set_int(u, "ip", ip); } break; } case 0x0c: /* DC info */ { struct { uint32_t ip; uint32_t port; uint8_t tcp_flag; uint16_t version; uint32_t conn_cookie; uint32_t web_port; uint32_t client_features; /* faked time signatures, used to identify clients */ uint32_t ts1; uint32_t ts2; uint32_t ts3; uint16_t junk; } tlv_c; if (!icq_unpack_nc(t->buf, t->len, "IICWIII", &tlv_c.ip, &tlv_c.port, &tlv_c.tcp_flag, &tlv_c.version, &tlv_c.conn_cookie, &tlv_c.web_port, &tlv_c.client_features)) { debug_error(" %s TLV(C) corrupted?\n", u->uid); continue; } else { user_private_item_set_int(u, "dcc.ip", tlv_c.ip); user_private_item_set_int(u, "dcc.port", tlv_c.port); user_private_item_set_int(u, "dcc.flag", tlv_c.tcp_flag); user_private_item_set_int(u, "version", tlv_c.version); user_private_item_set_int(u, "dcc.cookie", tlv_c.conn_cookie); user_private_item_set_int(u, "dcc.web_port", tlv_c.web_port); // ?wo? do we need it? if (t->len >= 12 && icq_unpack_nc(t->buf, t->len, "23 III", &tlv_c.ts1, &tlv_c.ts3, &tlv_c.ts3)) ; } break; } case 0x0d: /* Client capabilities list */ { unsigned char *data = t->buf; int d_len = t->len; if (tlv_length_check("icq_get_user_info()", t, t->len & ~0xF)) break; while (d_len > 0) { int cid = icq_cap_id(data); if (cid != CAP_UNKNOWN) { caps |= 1 << cid; } else if ((cid = icq_xstatus_id(data))) { user_private_item_set_int(u, "xstatus", cid); } else { /* ?wo? client id???*/ debug_error("Unknown cap\n"); icq_hexdump(DEBUG_ERROR, data, 0x10); } data += 0x10; // capability length d_len -= 0x10; } break; } case 0x0e: /* AOL users. No values */ break; case 0x0f: case 0x10: /* Online time in seconds */ break; case 0x19: /* short caps */ { unsigned char *data = t->buf; int d_len = t->len; while (d_len > 0) { int cid = icq_short_cap_id(data); if (cid != CAP_UNKNOWN) { caps |= 1 << cid; } else { /* WTF? */ } data += 2; // short capability length d_len -= 2; } break; } case 0x1d: /* user icon id & hash */ { static char empty_item[0x10] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; unsigned char *t_data = t->buf; int t_len = t->len; while (t_len > 0) { uint16_t item_type; uint8_t item_flags; uint8_t item_len; if (!icq_unpack(t_data, &t_data, &t_len, "WCC", &item_type, &item_flags, &item_len)) { debug_error(" %s TLV(1D) corrupted?\n", u->uid); break; } /* just some validity check */ if (item_len > t_len) item_len = t_len; if ((item_type == 0x02) && (item_flags == 4)) { /* iChat online message */ if (item_len>4) { char *tmp; uint16_t enc; icq_unpack_nc(t_data, item_len, "Uw", &tmp, &enc); descr = !enc ? ekg_utf8_to_locale_dup(tmp) : xstrdup(tmp); } desc_chg = 1; } else if ((item_type == 0x0e) && (item_len>7)) { /* 000E: Custom Status (ICQ6) */ char *tmp = xstrndup((char *)t_data, item_len); if ( !xstrncmp(tmp, "icqmood", 7) && xisdigit(*(tmp+7)) ) { int xstatus = atoi(tmp+7) + 1; if (xstatus<=XSTATUS_COUNT) user_private_item_set_int(u, "xstatus", xstatus); } xfree(tmp); } else if (memcmp(t_data, empty_item, (item_len < 0x10) ? item_len : 0x10)) { /* Item types * 0000: AIM mini avatar * 0001: AIM/ICQ avatar ID/hash (len 5 or 16 bytes) * 0002: iChat online message * 0008: ICQ Flash avatar hash (16 bytes) * 0009: iTunes music store link * 000C: ICQ contact photo (16 bytes) * 000D: ? */ debug_white(" %s has got avatar: type: %d flags: %d\n", u->uid, item_type, item_flags); icq_hexdump(DEBUG_WHITE, t_data, item_len); /* XXX, display message, get? do something? */ } t_data += item_len; t_len -= item_len; } break; } default: if (t->len==4) debug_warn(" %s Unknown TLV(0x%x) len=4 v=%d (0x%x) (%s)\n", u->uid, t->type, t->nr, t->nr, t->nr?timestamp_time("%Y-%m-%d %H:%M:%S", t->nr):""); else debug_error(" %s Unknown TLV(0x%x) len=%d\n", u->uid, t->type, t->len); } } if (desc_chg || (newstatus != u->status)) { if (!descr && !desc_chg && u->descr) descr = xstrdup(u->descr); protocol_status_emit(s, u->uid, newstatus, descr, time(NULL)); } if (!desc_chg) { if (u->status == EKG_STATUS_NA) { icq_send_snac(s, 0x02, 0x05, NULL, NULL, /* Request user info */ "Ws", (uint32_t) 1, /* request type (1 - general info, 2 - short user info, 3 - away message, 4 - client capabilities) */ u->uid+4); } else { icq_get_description(s, u->uid+4, u->status); } } if (u->status == EKG_STATUS_NA) { user_private_item_set_int(u, "online", 0); user_private_item_set_int(u, "last_ip", user_private_item_get_int(u, "ip")); user_private_item_set_int(u, "ip", 0); if (user_private_item_get_int(u, "version") < 8) { caps &= ~(1<<CAP_SRV_RELAY); debug_warn("icq_snac_buddy_online() Forcing simple messages due to compatibility issues (%s).\n", u->uid); } } user_private_item_set_int(u, "caps", caps); user_private_item_set_int(u, "utf", (caps && (1<<CAP_UTF)) ? 1:0); xfree(descr); }
/* * variable_set() * * ustawia warto¶æ podanej zmiennej. je¶li to zmienna liczbowa lub boolowska, * zmienia ci±g na liczbê. w przypadku boolowskich, rozumie zwroty typu `on', * `off', `yes', `no' itp. je¶li dana zmienna jest bitmap±, akceptuje warto¶æ * w postaci listy flag oraz konstrukcje `+flaga' i `-flaga'. * * - name - nazwa zmiennej, * - value - nowa warto¶æ, */ int variable_set(const char *name, const char *value) { variable_t *v = variable_find(name); char *tmpname; int changed = 0; if (!v) return -1; switch (v->type) { case VAR_INT: case VAR_MAP: { const char *p = value; int hex, tmp; if (!value) return -2; if (v->map && v->type == VAR_INT && !xisdigit(*p)) { int i; for (i = 0; v->map[i].label; i++) if (!xstrcasecmp(v->map[i].label, value)) value = ekg_itoa(v->map[i].value); } if (v->map && v->type == VAR_MAP && !xisdigit(*p)) { int i, k = *(int*)(v->ptr); int mode = 0; /* 0 set, 1 add, 2 remove */ char **args; if (*p == '+') { mode = 1; p++; } else if (*p == '-') { mode = 2; p++; } if (!mode) k = 0; args = array_make(p, ",", 0, 1, 0); for (i = 0; args[i]; i++) { int j, found = 0; for (j = 0; v->map[j].label; j++) { if (!xstrcasecmp(args[i], v->map[j].label)) { found = 1; if (mode == 2) k &= ~(v->map[j].value); if (mode == 1) k &= ~(v->map[j].conflicts); if (mode == 1 || !mode) k |= v->map[j].value; } } if (!found) { g_strfreev(args); return -2; } } g_strfreev(args); value = ekg_itoa(k); } p = value; if ((hex = !xstrncasecmp(p, "0x", 2))) p += 2; while (*p && *p != ' ') { if (hex && !xisxdigit(*p)) return -2; if (!hex && !xisdigit(*p)) return -2; p++; } tmp = strtol(value, NULL, 0); if (v->map) { int i; for (i = 0; v->map[i].label; i++) { if ((tmp & v->map[i].value) && (tmp & v->map[i].conflicts)) return -2; } } changed = (*(int*)(v->ptr) != tmp); *(int*)(v->ptr) = tmp; break; } case VAR_BOOL: { int tmp; if (!value) return -2; if ((tmp = on_off(value)) == -1) return -2; changed = (*(int*)(v->ptr) != tmp); *(int*)(v->ptr) = tmp; break; } case VAR_THEME: case VAR_FILE: case VAR_DIR: case VAR_STR: { char **tmp = (char**)(v->ptr); char *oldval = *tmp; if (value) { if (*value == 1) *tmp = base64_decode(value + 1); else *tmp = xstrdup(value); } else *tmp = NULL; changed = xstrcmp(oldval, *tmp); xfree(oldval); break; } default: return -1; } if (v->notify) (v->notify)(v->name); if (!changed) return 1; tmpname = xstrdup(v->name); query_emit(NULL, "variable-changed", &tmpname); xfree(tmpname); return 0; }
/* * variable_set() * * ustawia warto¶æ podanej zmiennej. je¶li to zmienna liczbowa lub boolowska, * zmienia ci±g na liczbê. w przypadku boolowskich, rozumie zwroty typu `on', * `off', `yes', `no' itp. je¶li dana zmienna jest bitmap±, akceptuje warto¶æ * w postaci listy flag oraz konstrukcje `+flaga' i `-flaga'. * * - name - nazwa zmiennej, * - value - nowa warto¶æ, * - allow_foreign - czy ma pozwalaæ dopisywaæ obce zmienne. */ int variable_set(const char *name, const char *value, int allow_foreign) { struct variable *v = variable_find(name); if (!v && allow_foreign) { variable_add(name, "##", VAR_FOREIGN, 2, xstrdup(value), NULL, NULL, NULL); return -1; } if (!v && !allow_foreign) return -1; switch (v->type) { case VAR_INT: case VAR_MAP: { const char *p = value; int hex, tmp; if (!value) return -2; if (v->map && v->type == VAR_INT && !xisdigit(*p)) { int i; for (i = 0; v->map[i].label; i++) if (!strcasecmp(v->map[i].label, value)) value = itoa(v->map[i].value); } if (v->map && v->type == VAR_MAP && !xisdigit(*p)) { int i, k = *(int*)(v->ptr); int mode = 0; /* 0 set, 1 add, 2 remove */ char **args; if (*p == '+') { mode = 1; p++; } else if (*p == '-') { mode = 2; p++; } if (!mode) k = 0; args = array_make(p, ",", 0, 1, 0); for (i = 0; args[i]; i++) { int j, found = 0; for (j = 0; v->map[j].label; j++) { if (!strcasecmp(args[i], v->map[j].label)) { found = 1; if (mode == 2) k &= ~(v->map[j].value); if (mode == 1) k &= ~(v->map[j].conflicts); if (mode == 1 || !mode) k |= v->map[j].value; } } if (!found) { array_free(args); return -2; } } array_free(args); value = itoa(k); } p = value; if ((hex = !strncasecmp(p, "0x", 2))) p += 2; while (*p && *p != ' ') { if (hex && !xisxdigit(*p)) return -2; if (!hex && !xisdigit(*p)) return -2; p++; } tmp = strtol(value, NULL, 0); if (v->map) { int i; for (i = 0; v->map[i].label; i++) { if ((tmp & v->map[i].value) && (tmp & v->map[i].conflicts)) return -2; } } *(int*)(v->ptr) = tmp; if (v->notify) (v->notify)(v->name); if (ui_event) ui_event("variable_changed", v->name); return 0; } case VAR_BOOL: { int tmp; if (!value) return -2; if ((tmp = on_off(value)) == -1) return -2; *(int*)(v->ptr) = tmp; if (v->notify) (v->notify)(v->name); if (ui_event) ui_event("variable_changed", v->name); return 0; } case VAR_STR: { char **tmp = (char**)(v->ptr); xfree(*tmp); if (value) { if (*value == 1) *tmp = base64_decode(value + 1); else *tmp = xstrdup(value); } else *tmp = NULL; if (v->notify) (v->notify)(v->name); if (ui_event) ui_event("variable_changed", v->name); return 0; } } return -1; }
eight_bits #line 317 "./cwebdir/ctang-w2c.ch" get_next P1H(void) #line 903 "./cwebdir/ctangle.w" { static int preprocessing= 0; eight_bits c; while(1){ if(loc> limit){ if(preprocessing&&*(limit-1)!='\\')preprocessing= 0; if(get_line()==0)return(new_section); else if(print_where&&!no_where){ print_where= 0; /*76:*/ #line 1225 "./cwebdir/ctangle.w" store_two_bytes(0150000); if(changing)id_first= change_file_name; else id_first= cur_file_name; id_loc= id_first+strlen(id_first); if(changing)store_two_bytes((sixteen_bits)change_line); else store_two_bytes((sixteen_bits)cur_line); {int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200); app_repl(a%0400);} /*:76*/ #line 912 "./cwebdir/ctangle.w" ; } else return('\n'); } c= *loc; if(comment_continues||(c=='/'&&(*(loc+1)=='*'||*(loc+1)=='/'))){ skip_comment(comment_continues||*(loc+1)=='*'); if(comment_continues)return('\n'); else continue; } loc++; if(xisdigit(c)||c=='.')/*65:*/ #line 978 "./cwebdir/ctangle.w" { id_first= loc-1; if(*id_first=='.'&&!xisdigit(*loc))goto mistake; if(*id_first=='0'){ if(*loc=='x'||*loc=='X'){ loc++;while(xisxdigit(*loc))loc++;goto found; } } while(xisdigit(*loc))loc++; if(*loc=='.'){ loc++; while(xisdigit(*loc))loc++; } if(*loc=='e'||*loc=='E'){ if(*++loc=='+'||*loc=='-')loc++; while(xisdigit(*loc))loc++; } found:while(*loc=='u'||*loc=='U'||*loc=='l'||*loc=='L' ||*loc=='f'||*loc=='F')loc++; id_loc= loc; return(constant); } /*:65*/ #line 924 "./cwebdir/ctangle.w" else if(c=='\''||c=='"'||(c=='L'&&(*loc=='\''||*loc=='"'))) /*66:*/ #line 1006 "./cwebdir/ctangle.w" { char delim= c; id_first= section_text+1; id_loc= section_text;*++id_loc= delim; if(delim=='L'){ delim= *loc++;*++id_loc= delim; } while(1){ if(loc>=limit){ if(*(limit-1)!='\\'){ err_print("! String didn't end");loc= limit;break; } if(get_line()==0){ err_print("! Input ended in middle of string");loc= buffer;break; } else if(++id_loc<=section_text_end)*id_loc= '\n'; } if((c= *loc++)==delim){ if(++id_loc<=section_text_end)*id_loc= c; break; } if(c=='\\'){ if(loc>=limit)continue; if(++id_loc<=section_text_end)*id_loc= '\\'; c= *loc++; } if(++id_loc<=section_text_end)*id_loc= c; } if(id_loc>=section_text_end){ printf("\n! String too long: "); term_write(section_text+1,25); err_print("..."); } id_loc++; return(string); } /*:66*/ #line 926 "./cwebdir/ctangle.w" else if(isalpha(c)||isxalpha(c)||ishigh(c)) /*64:*/ #line 972 "./cwebdir/ctangle.w" { id_first= --loc; while(isalpha(*++loc)||isdigit(*loc)||isxalpha(*loc)||ishigh(*loc)); id_loc= loc;return(identifier); } /*:64*/ #line 928 "./cwebdir/ctangle.w" else if(c=='@')/*67:*/ #line 1050 "./cwebdir/ctangle.w" { c= ccode[(eight_bits)*loc++]; switch(c){ case ignore:continue; case translit_code:err_print("! Use @l in limbo only");continue; case control_text:while((c= skip_ahead())=='@'); if(*(loc-1)!='>') err_print("! Double @ should be used in control text"); continue; case section_name: cur_section_name_char= *(loc-1); /*69:*/ #line 1098 "./cwebdir/ctangle.w" { char*k; /*71:*/ #line 1118 "./cwebdir/ctangle.w" k= section_text; while(1){ if(loc> limit&&get_line()==0){ err_print("! Input ended in section name"); loc= buffer+1;break; } c= *loc; /*72:*/ #line 1142 "./cwebdir/ctangle.w" if(c=='@'){ c= *(loc+1); if(c=='>'){ loc+= 2;break; } if(ccode[(eight_bits)c]==new_section){ err_print("! Section name didn't end");break; } if(ccode[(eight_bits)c]==section_name){ err_print("! Nesting of section names not allowed");break; } *(++k)= '@';loc++; } /*:72*/ #line 1127 "./cwebdir/ctangle.w" ; loc++;if(k<section_text_end)k++; if(xisspace(c)){ c= ' ';if(*(k-1)==' ')k--; } *k= c; } if(k>=section_text_end){ printf("\n! Section name too long: "); term_write(section_text+1,25); printf("...");mark_harmless; } if(*k==' '&&k> section_text)k--; /*:71*/ #line 1100 "./cwebdir/ctangle.w" ; if(k-section_text> 3&&strncmp(k-2,"...",3)==0) cur_section_name= section_lookup(section_text+1,k-3,1); else cur_section_name= section_lookup(section_text+1,k,0); if(cur_section_name_char=='(') /*39:*/ #line 516 "./cwebdir/ctangle.w" { for(an_output_file= cur_out_file; an_output_file<end_output_files;an_output_file++) if(*an_output_file==cur_section_name)break; if(an_output_file==end_output_files){ if(cur_out_file> output_files) *--cur_out_file= cur_section_name; else{ overflow("output files"); } } } /*:39*/ #line 1106 "./cwebdir/ctangle.w" ; return(section_name); } /*:69*/ #line 1064 "./cwebdir/ctangle.w" ; case string:/*73:*/ #line 1164 "./cwebdir/ctangle.w" { id_first= loc++;*(limit+1)= '@';*(limit+2)= '>'; while(*loc!='@'||*(loc+1)!='>')loc++; if(loc>=limit)err_print("! Verbatim string didn't end"); id_loc= loc;loc+= 2; return(string); } /*:73*/ #line 1065 "./cwebdir/ctangle.w" ; case ord:/*68:*/ #line 1077 "./cwebdir/ctangle.w" id_first= loc; if(*loc=='\\'){ if(*++loc=='\'')loc++; } while(*loc!='\''){ if(*loc=='@'){ if(*(loc+1)!='@') err_print("! Double @ should be used in ASCII constant"); else loc++; } loc++; if(loc> limit){ err_print("! String didn't end");loc= limit-1;break; } } loc++; return(ord); /*:68*/ #line 1066 "./cwebdir/ctangle.w" ; default:return(c); } } /*:67*/ #line 929 "./cwebdir/ctangle.w" else if(xisspace(c)){ if(!preprocessing||loc> limit)continue; else return(' '); } else if(c=='#'&&loc==buffer+1)preprocessing= 1; mistake:/*63:*/ #line 950 "./cwebdir/ctangle.w" switch(c){ case'+':if(*loc=='+')compress(plus_plus);break; case'-':if(*loc=='-'){compress(minus_minus);} else if(*loc=='>')if(*(loc+1)=='*'){loc++;compress(minus_gt_ast);} else compress(minus_gt);break; case'.':if(*loc=='*'){compress(period_ast);} else if(*loc=='.'&&*(loc+1)=='.'){ loc++;compress(dot_dot_dot); } break; case':':if(*loc==':')compress(colon_colon);break; case'=':if(*loc=='=')compress(eq_eq);break; case'>':if(*loc=='='){compress(gt_eq);} else if(*loc=='>')compress(gt_gt);break; case'<':if(*loc=='='){compress(lt_eq);} else if(*loc=='<')compress(lt_lt);break; case'&':if(*loc=='&')compress(and_and);break; case'|':if(*loc=='|')compress(or_or);break; case'!':if(*loc=='=')compress(not_eq);break; } /*:63*/ #line 936 "./cwebdir/ctangle.w" return(c); } }
void #line 326 "./cwebdir/ctang-w2c.ch" scan_repl P1C(eight_bits,t) #line 1203 "./cwebdir/ctangle.w" { sixteen_bits a; if(t==section_name){/*76:*/ #line 1225 "./cwebdir/ctangle.w" store_two_bytes(0150000); if(changing)id_first= change_file_name; else id_first= cur_file_name; id_loc= id_first+strlen(id_first); if(changing)store_two_bytes((sixteen_bits)change_line); else store_two_bytes((sixteen_bits)cur_line); {int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200); app_repl(a%0400);} /*:76*/ #line 1205 "./cwebdir/ctangle.w" ;} while(1)switch(a= get_next()){ /*77:*/ #line 1235 "./cwebdir/ctangle.w" case identifier:a= id_lookup(id_first,id_loc,0)-name_dir; app_repl((a/0400)+0200); app_repl(a%0400);break; case section_name:if(t!=section_name)goto done; else{ /*78:*/ #line 1268 "./cwebdir/ctangle.w" { char*try_loc= loc; while(*try_loc==' '&&try_loc<limit)try_loc++; if(*try_loc=='+'&&try_loc<limit)try_loc++; while(*try_loc==' '&&try_loc<limit)try_loc++; if(*try_loc=='=')err_print("! Missing `@ ' before a named section"); } /*:78*/ #line 1241 "./cwebdir/ctangle.w" ; a= cur_section_name-name_dir; app_repl((a/0400)+0250); app_repl(a%0400); /*76:*/ #line 1225 "./cwebdir/ctangle.w" store_two_bytes(0150000); if(changing)id_first= change_file_name; else id_first= cur_file_name; id_loc= id_first+strlen(id_first); if(changing)store_two_bytes((sixteen_bits)change_line); else store_two_bytes((sixteen_bits)cur_line); {int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200); app_repl(a%0400);} /*:76*/ #line 1245 "./cwebdir/ctangle.w" ;break; } case output_defs_code:if(t!=section_name)err_print("! Misplaced @h"); else{ output_defs_seen= 1; a= output_defs_flag; app_repl((a/0400)+0200); app_repl(a%0400); /*76:*/ #line 1225 "./cwebdir/ctangle.w" store_two_bytes(0150000); if(changing)id_first= change_file_name; else id_first= cur_file_name; id_loc= id_first+strlen(id_first); if(changing)store_two_bytes((sixteen_bits)change_line); else store_two_bytes((sixteen_bits)cur_line); {int a= id_lookup(id_first,id_loc,0)-name_dir;app_repl((a/0400)+0200); app_repl(a%0400);} /*:76*/ #line 1254 "./cwebdir/ctangle.w" ; } break; case constant:case string: /*79:*/ #line 1279 "./cwebdir/ctangle.w" app_repl(a); while(id_first<id_loc){ if(*id_first=='@'){ if(*(id_first+1)=='@')id_first++; else err_print("! Double @ should be used in string"); } app_repl(*id_first++); } app_repl(a);break; /*:79*/ #line 1258 "./cwebdir/ctangle.w" ; case ord: /*80:*/ #line 1295 "./cwebdir/ctangle.w" { int c= (eight_bits)*id_first; if(c=='\\'){ c= *++id_first; if(c>='0'&&c<='7'){ c-= '0'; if(*(id_first+1)>='0'&&*(id_first+1)<='7'){ c= 8*c+*(++id_first)-'0'; if(*(id_first+1)>='0'&&*(id_first+1)<='7'&&c<32) c= 8*c+*(++id_first)-'0'; } } else switch(c){ case't':c= '\t';break; case'n':c= '\n';break; case'b':c= '\b';break; case'f':c= '\f';break; case'v':c= '\v';break; case'r':c= '\r';break; case'a':c= '\7';break; case'?':c= '?';break; case'x': if(xisdigit(*(id_first+1)))c= *(++id_first)-'0'; else if(xisxdigit(*(id_first+1))){ ++id_first; c= toupper(*id_first)-'A'+10; } if(xisdigit(*(id_first+1)))c= 16*c+*(++id_first)-'0'; else if(xisxdigit(*(id_first+1))){ ++id_first; c= 16*c+toupper(*id_first)-'A'+10; } break; case'\\':c= '\\';break; case'\'':c= '\'';break; case'\"':c= '\"';break; default:err_print("! Unrecognized escape sequence"); } } app_repl(constant); if(c>=100)app_repl('0'+c/100); if(c>=10)app_repl('0'+(c/10)%10); app_repl('0'+c%10); app_repl(constant); } break; /*:80*/ #line 1260 "./cwebdir/ctangle.w" ; case definition:case format_code:case begin_C:if(t!=section_name)goto done; else{ err_print("! @d, @f and @c are ignored in C text");continue; } case new_section:goto done; /*:77*/ #line 1210 "./cwebdir/ctangle.w" case')':app_repl(a); if(t==macro)app_repl(' '); break; default:app_repl(a); } done:next_control= (eight_bits)a; if(text_ptr> text_info_end)overflow("text"); cur_text= text_ptr;(++text_ptr)->tok_start= tok_ptr; }
rpmRC lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkgp) { HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); char *NV = NULL; char *N = NULL; char *V = NULL; Package p; Package lastp = spec->packages; rpmRC rc = RPMRC_OK; int xx; if (lastp == NULL) /* XXX segfault avoidance */ goto exit; /* "main" package */ if (name == NULL) goto exit; /* Construct package name */ if (flag == PART_SUBNAME) { he->tag = RPMTAG_NAME; xx = headerGet(spec->packages->header, he, 0); assert(xx != 0 && he->p.str != NULL); N = rpmExpand(he->p.str, "-", name, NULL); he->p.ptr = _free(he->p.ptr); } else { N = xstrdup(name); /* XXX restrict V to leading digit to prevent NV split ambiguity. */ if ((V = strrchr(N, '-')) != NULL && xisdigit(V[1])) { NV = xstrdup(N); *V++ = '\0'; } else V = NULL; } /* Match last package with same N or same {N,V} */ lastp = NULL; for (p = spec->packages; p != NULL; p = p->next) { char *nv, *n, *v; nv = n = v = NULL; he->tag = RPMTAG_NAME; xx = headerGet(p->header, he, 0); if (xx && he->p.str != NULL) { n = (char *) he->p.str; he->p.str = NULL; } if (NV != NULL) { he->tag = RPMTAG_VERSION; xx = headerGet(p->header, he, 0); if (xx && he->p.str != NULL) { v = (char *) he->p.str; he->p.str = NULL; nv = rpmExpand(n, "-", v, NULL); } } if (NV == NULL) { if ((n && !strcmp(N, n))) lastp = p; } else { if ((nv && !strcmp(NV, nv)) || (n && !strcmp(NV, n)) || ((n && !strcmp(N, n)) && (V == NULL || (v && !strcmp(V, v))))) lastp = p; } /*@-usereleased@*/ n = _free(n); v = _free(v); nv = _free(nv); /*@=usereleased@*/ } rc = (lastp == NULL ? RPMRC_FAIL : RPMRC_OK); NV = _free(NV); N = _free(N); exit: if (pkgp) /*@-dependenttrans@*/ *pkgp = lastp; /*@=dependenttrans@*/ return rc; }
void vmain(void) { int c, cnt, i; cell esave[TUBECOLS]; char *oglobp; short d; line *addr; int ind, nlput; int shouldpo = 0; int onumber = 0, olist = 0; void (*OPline)(int) = NULL; int (*OPutchar)(int) = NULL; CLOBBGRD(c); CLOBBGRD(cnt); CLOBBGRD(i); CLOBBGRD(oglobp); CLOBBGRD(addr); CLOBBGRD(shouldpo); CLOBBGRD(onumber); CLOBBGRD(olist); CLOBBGRD(OPline); CLOBBGRD(OPutchar); vch_mac = VC_NOTINMAC; /* * If we started as a vi command (on the command line) * then go process initial commands (recover, next or tag). */ if (initev) { oglobp = globp; globp = initev; hadcnt = cnt = 0; i = tchng; addr = dot; goto doinit; } /* * NB: * * The current line is always in the line buffer linebuf, * and the cursor at the position cursor. You should do * a vsave() before moving off the line to make sure the disk * copy is updated if it has changed, and a getDOT() to get * the line back if you mung linebuf. The motion * routines in ex_vwind.c handle most of this. */ for (;;) { /* * Decode a visual command. * First sync the temp file if there has been a reasonable * amount of change. Clear state for decoding of next * command. */ TSYNC(); vglobp = 0; vreg = 0; hold = 0; seenprompt = 1; wcursor = 0; Xhadcnt = hadcnt = 0; Xcnt = cnt = 1; splitw = 0; if (i = holdupd) { if (state == VISUAL) ignore(peekkey()); holdupd = 0; /* if (LINE(0) < ZERO) { vclear(); vcnt = 0; i = 3; } */ if (state != VISUAL) { vcnt = 0; vsave(); vrepaint(cursor); } else if (i == 3) vredraw(WTOP); else vsync(WTOP); vfixcurs(); } /* * Gobble up counts and named buffer specifications. */ for (;;) { looptop: #ifdef MDEBUG if (trace) fprintf(trace, "pc=%c",peekkey()); #endif if (xisdigit(peekkey()) && peekkey() != '0') { hadcnt = 1; cnt = vgetcnt(); forbid (cnt <= 0); } if (peekkey() != '"') break; ignore(getkey()), c = getkey(); /* * Buffer names be letters or digits. * But not '0' as that is the source of * an 'empty' named buffer spec in the routine * kshift (see ex_temp.c). */ forbid (c == '0' || !xisalpha(c) && !xisdigit(c)); vreg = c; } reread: /* * Come to reread from below after some macro expansions. * The call to map allows use of function key pads * by performing a terminal dependent mapping of inputs. */ #ifdef MDEBUG if (trace) fprintf(trace,"pcb=%c,",peekkey()); #endif op = getkey(); maphopcnt = 0; do { /* * Keep mapping the char as long as it changes. * This allows for double mappings, e.g., q to #, * #1 to something else. */ c = op; op = map(c,arrows); #ifdef MDEBUG if (trace) fprintf(trace,"pca=%c,",c); #endif /* * Maybe the mapped to char is a count. If so, we have * to go back to the "for" to interpret it. Likewise * for a buffer name. */ if ((xisdigit(c) && c!='0') || c == '"') { ungetkey(c); goto looptop; } if (!value(REMAP)) { c = op; break; } if (++maphopcnt > 256) error(catgets(catd, 1, 225, "Infinite macro loop")); } while (c != op); /* * Begin to build an image of this command for possible * later repeat in the buffer workcmd. It will be copied * to lastcmd by the routine setLAST * if/when completely specified. */ lastcp = workcmd; if (!vglobp) *lastcp++ = c; /* * First level command decode. */ if (c == ATTN) goto case_ATTN; switch (c) { /* * ^L Clear screen e.g. after transmission error. */ /* * ^R Retype screen, getting rid of @ lines. * If in open, equivalent to ^L. * On terminals where the right arrow key sends * ^L we make ^R act like ^L, since there is no * way to get ^L. These terminals (adm31, tvi) * are intelligent so ^R is useless. Soroc * will probably foul this up, but nobody has * one of them. */ case CTRL('l'): case CTRL('r'): if (c == CTRL('l') || (KR && *KR==CTRL('l'))) { vclear(); vdirty(0, vcnt); } if (state != VISUAL) { /* * Get a clean line, throw away the * memory of what is displayed now, * and move back onto the current line. */ vclean(); vcnt = 0; vmoveto(dot, cursor, 0); continue; } vredraw(WTOP); /* * Weird glitch -- when we enter visual * in a very small window we may end up with * no lines on the screen because the line * at the top is too long. This forces the screen * to be expanded to make room for it (after * we have printed @'s ick showing we goofed). */ if (vcnt == 0) vrepaint(cursor); vfixcurs(); continue; /* * $ Escape just cancels the current command * with a little feedback. */ case ESCAPE: beep(); continue; /* * @ Macros. Bring in the macro and put it * in vmacbuf, point vglobp there and punt. */ case '@': c = getesc(); if (c == 0) continue; if (c == '@') c = lastmac; if (xisupper(c)) c = xtolower(c); forbid(!xislower(c)); lastmac = c; vsave(); CATCH char tmpbuf[BUFSIZ]; regbuf(c,tmpbuf,sizeof(vmacbuf)); macpush(tmpbuf, 1); ONERR lastmac = 0; splitw = 0; getDOT(); vrepaint(cursor); continue; ENDCATCH vmacp = vmacbuf; goto reread; /* * . Repeat the last (modifying) open/visual command. */ case '.': /* * Check that there was a last command, and * take its count and named buffer unless they * were given anew. Special case if last command * referenced a numeric named buffer -- increment * the number and go to a named buffer again. * This allows a sequence like "1pu.u.u... * to successively look for stuff in the kill chain * much as one does in EMACS with C-Y and M-Y. */ forbid (lastcmd[0] == 0); if (hadcnt) lastcnt = cnt; if (vreg) lastreg = vreg; else if (xisdigit(lastreg) && lastreg < '9') lastreg++; vreg = lastreg; cnt = lastcnt; hadcnt = lasthad; vglobp = lastcmd; goto reread; /* * ^U Scroll up. A count sticks around for * future scrolls as the scroll amount. * Attempt to hold the indentation from the * top of the screen (in logical lines). * * BUG: A ^U near the bottom of the screen * on a dumb terminal (which can't roll back) * causes the screen to be cleared and then * redrawn almost as it was. In this case * one should simply move the cursor. */ case CTRL('u'): if (hadcnt) vSCROLL = cnt; cnt = vSCROLL; if (state == VISUAL) ind = vcline, cnt += ind; else ind = 0; vmoving = 0; vup(cnt, ind, 1); vnline(NOSTR); continue; /* * ^D Scroll down. Like scroll up. */ case CTRL('d'): #ifdef TRACE if (trace) fprintf(trace, "before vdown in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); #endif if (hadcnt) vSCROLL = cnt; cnt = vSCROLL; if (state == VISUAL) ind = vcnt - vcline - 1, cnt += ind; else ind = 0; vmoving = 0; vdown(cnt, ind, 1); #ifdef TRACE if (trace) fprintf(trace, "before vnline in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); #endif vnline(NOSTR); #ifdef TRACE if (trace) fprintf(trace, "after vnline in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); #endif continue; /* * ^E Glitch the screen down (one) line. * Cursor left on same line in file. */ case CTRL('e'): if (state != VISUAL) continue; if (!hadcnt) cnt = 1; /* Bottom line of file already on screen */ forbid(lineDOL()-lineDOT() <= vcnt-1-vcline); ind = vcnt - vcline - 1 + cnt; vdown(ind, ind, 1); vnline(cursor); continue; /* * ^Y Like ^E but up */ case CTRL('y'): if (state != VISUAL) continue; if (!hadcnt) cnt = 1; forbid(lineDOT()-1<=vcline); /* line 1 already there */ ind = vcline + cnt; vup(ind, ind, 1); vnline(cursor); continue; /* * m Mark position in mark register given * by following letter. Return is * accomplished via ' or `; former * to beginning of line where mark * was set, latter to column where marked. */ case 'm': /* * Getesc is generally used when a character * is read as a latter part of a command * to allow one to hit rubout/escape to cancel * what you have typed so far. These characters * are mapped to 0 by the subroutine. */ c = getesc(); if (c == 0) continue; /* * Markreg checks that argument is a letter * and also maps ' and ` to the end of the range * to allow '' or `` to reference the previous * context mark. */ c = markreg(c); forbid (c == 0); vsave(); names[c - 'a'] = (*dot &~ 01); ncols[c - 'a'] = cursor; anymarks = 1; continue; /* * ^F Window forwards, with 2 lines of continuity. * Count repeats. */ case CTRL('f'): vsave(); if (vcnt > 2) { addr = dot + (vcnt - vcline) - 2 + (cnt-1)*basWLINES; forbid(addr > dol); dot = (line*)addr; vcnt = vcline = 0; } vzop(0, 0, '+'); continue; /* * ^B Window backwards, with 2 lines of continuity. * Inverse of ^F. */ case CTRL('b'): vsave(); if (one + vcline != dot && vcnt > 2) { addr = dot - vcline + 2 - (cnt-1)*basWLINES; forbid (addr <= zero); dot = (line*)addr; vcnt = vcline = 0; } vzop(0, 0, '^'); continue; /* * z Screen adjustment, taking a following character: * z<CR> current line to top * z<NL> like z<CR> * z- current line to bottom * also z+, z^ like ^F and ^B. * A preceding count is line to use rather * than current line. A count between z and * specifier character changes the screen size * for the redraw. * */ case 'z': if (state == VISUAL) { i = vgetcnt(); if (i > 0) vsetsiz(i); c = getesc(); if (c == 0) continue; } vsave(); vzop(hadcnt, cnt, c); continue; /* * Y Yank lines, abbreviation for y_ or yy. * Yanked lines can be put later if no * changes intervene, or can be put in named * buffers and put anytime in this session. */ case 'Y': ungetkey('_'); c = 'y'; break; /* * J Join lines, 2 by default. Count is number * of lines to join (no join operator sorry.) */ case 'J': forbid (dot == dol); if (cnt == 1) cnt = 2; if (cnt > (i = dol - dot + 1)) cnt = i; vsave(); vmacchng(1); setLAST(); cursor = strend(linebuf); vremote(cnt, join, 0); notenam = "join"; vmoving = 0; killU(); vreplace(vcline, cnt, 1); if (!*cursor && cursor > linebuf) cursor += skipleft(linebuf, cursor); if (notecnt == 2) notecnt = 0; vrepaint(cursor); continue; /* * S Substitute text for whole lines, abbrev for c_. * Count is number of lines to change. */ case 'S': ungetkey('_'); c = 'c'; break; /* * O Create a new line above current and accept new * input text, to an escape, there. * A count specifies, for dumb terminals when * slowopen is not set, the number of physical * line space to open on the screen. * * o Like O, but opens lines below. */ case 'O': case 'o': vmacchng(1); voOpen(c, cnt); continue; /* * C Change text to end of line, short for c$. */ case 'C': if (*cursor) { ungetkey('$'), c = 'c'; break; } goto appnd; /* * ~ Switch case of letter under cursor */ case '~': vswitch(cnt); continue; /* * A Append at end of line, short for $a. */ case 'A': operate('$', 1); appnd: c = 'a'; /* fall into ... */ /* * a Appends text after cursor. Text can continue * through arbitrary number of lines. */ case 'a': if (*cursor) { if (state == HARDOPEN) { int c, n; nextc(c, cursor, n); putchar(c); cursor += n; } else cursor += skipright(linebuf, cursor); } goto insrt; /* * I Insert at beginning of whitespace of line, * short for ^i. */ case 'I': operate('^', 1); c = 'i'; /* fall into ... */ /* * R Replace characters, one for one, by input * (logically), like repeated r commands. * * BUG: This is like the typeover mode of many other * editors, and is only rarely useful. Its * implementation is a hack in a low level * routine and it doesn't work very well, e.g. * you can't move around within a R, etc. */ case 'R': /* fall into... */ /* * i Insert text to an escape in the buffer. * Text is arbitrary. This command reminds of * the i command in bare teco. */ case 'i': insrt: /* * Common code for all the insertion commands. * Save for redo, position cursor, prepare for append * at command and in visual undo. Note that nothing * is doomed, unless R when all is, and save the * current line in a the undo temporary buffer. */ vmacchng(1); setLAST(); vcursat(cursor); prepapp(); vnoapp(); doomed = c == 'R' ? 10000 : 0; if(FIXUNDO) vundkind = VCHNG; vmoving = 0; CP(vutmp, linebuf); /* * If this is a repeated command, then suppress * fake insert mode on dumb terminals which looks * ridiculous and wastes lots of time even at 9600B. */ if (vglobp) hold = HOLDQIK; vappend(c, cnt, 0); continue; /* * ^? An attention, normally a ^?, just beeps. * If you are a vi command within ex, then * two ATTN's will drop you back to command mode. */ case_ATTN: beep(); if (initev || peekkey() != ATTN) continue; /* fall into... */ /* * ^\ A quit always gets command mode. */ case QUIT: /* * Have to be careful if we were called * g/xxx/vi * since a return will just start up again. * So we simulate an interrupt. */ if (inglobal) onintr(SIGINT); /* fall into... */ #ifdef notdef /* * q Quit back to command mode, unless called as * vi on command line in which case dont do it */ case 'q': /* quit */ if (initev) { vsave(); CATCH error(catgets(catd, 1, 226, "Q gets ex command mode, :q leaves vi")); ENDCATCH splitw = 0; getDOT(); vrepaint(cursor); continue; } #endif /* fall into... */ /* * Q Is like q, but always gets to command mode * even if command line invocation was as vi. */ case 'Q': vsave(); /* * If we are in the middle of a macro, throw away * the rest and fix up undo. * This code copied from getbr(). */ if (vmacp) { vmacp = 0; if (inopen == -1) /* don't screw up undo for esc esc */ vundkind = VMANY; inopen = 1; /* restore old setting now that macro done */ } return; /* * ZZ Like :x */ case 'Z': forbid(getkey() != 'Z'); oglobp = globp; globp = "x"; vclrech(0); goto gogo; /* * P Put back text before cursor or before current * line. If text was whole lines goes back * as whole lines. If part of a single line * or parts of whole lines splits up current * line to form many new lines. * May specify a named buffer, or the delete * saving buffers 1-9. * * p Like P but after rather than before. */ case 'P': case 'p': vmoving = 0; #ifdef notdef forbid (!vreg && value(UNDOMACRO) && inopen < 0); #endif /* * If previous delete was partial line, use an * append or insert to put it back so as to * use insert mode on intelligent terminals. */ if (!vreg && DEL[0]) { forbid ((DEL[0] & (QUOTE|TRIM)) == OVERBUF); vglobp = DEL; ungetkey(c == 'p' ? 'a' : 'i'); goto reread; } /* * If a register wasn't specified, then make * sure there is something to put back. */ forbid (!vreg && unddol == dol); /* * If we just did a macro the whole buffer is in * the undo save area. We don't want to put THAT. */ forbid (vundkind == VMANY && undkind==UNDALL); vsave(); vmacchng(1); setLAST(); i = 0; if (vreg && partreg(vreg) || !vreg && pkill[0]) { /* * Restoring multiple lines which were partial * lines; will leave cursor in middle * of line after shoving restored text in to * split the current line. */ i++; if (c == 'p' && *cursor) cursor += skipright(linebuf, cursor); } else { /* * In whole line case, have to back up dot * for P; also want to clear cursor so * cursor will eventually be positioned * at the beginning of the first put line. */ cursor = 0; if (c == 'P') { dot--, vcline--; c = 'p'; } } killU(); /* * The call to putreg can potentially * bomb since there may be nothing in a named buffer. * We thus put a catch in here. If we didn't and * there was an error we would end up in command mode. */ addr = dol; /* old dol */ CATCH vremote(1, vreg ? putreg : put, vreg); ONERR if (vreg == -1) { splitw = 0; if (op == 'P') dot++, vcline++; goto pfixup; } ENDCATCH splitw = 0; nlput = dol - addr + 1; if (!i) { /* * Increment undap1, undap2 to make up * for their incorrect initialization in the * routine vremote before calling put/putreg. */ if (FIXUNDO) undap1++, undap2++; vcline++; nlput--; /* * After a put want current line first line, * and dot was made the last line put in code * run so far. This is why we increment vcline * above and decrease dot here. */ dot -= nlput - 1; } #ifdef TRACE if (trace) fprintf(trace, "vreplace(%d, %d, %d), undap1=%d, undap2=%d, dot=%d\n", vcline, i, nlput, lineno(undap1), lineno(undap2), lineno(dot)); #endif vreplace(vcline, i, nlput); if (state != VISUAL) { /* * Special case in open mode. * Force action on the screen when a single * line is put even if it is identical to * the current line, e.g. on YP; otherwise * you can't tell anything happened. */ vjumpto(dot, cursor, '.'); continue; } pfixup: vrepaint(cursor); vfixcurs(); continue; /* * ^^ Return to previous file. * Like a :e #, and thus can be used after a * "No Write" diagnostic. */ case CTRL('^'): forbid (hadcnt); vsave(); ckaw(); oglobp = globp; if (value(AUTOWRITE)) globp = "e! #"; else globp = "e #"; goto gogo; /* * ^] Takes word after cursor as tag, and then does * tag command. Read ``go right to''. */ case CTRL(']'): grabtag(); oglobp = globp; globp = "tag"; goto gogo; /* * & Like :& */ case '&': oglobp = globp; globp = "&"; goto gogo; /* * ^G Bring up a status line at the bottom of * the screen, like a :file command. * * BUG: Was ^S but doesn't work in cbreak mode */ case CTRL('g'): oglobp = globp; globp = "file"; gogo: addr = dot; vsave(); goto doinit; #ifdef SIGTSTP /* * ^Z: suspend editor session and temporarily return * to shell. Only works with Berkeley/IIASA process * control in kernel. */ case CTRL('z'): forbid(dosusp == 0 || !ldisc); vsave(); oglobp = globp; globp = "stop"; goto gogo; #endif /* * : Read a command from the echo area and * execute it in command mode. */ case ':': forbid (hadcnt); vsave(); i = tchng; addr = dot; if (readecho(c)) { esave[0] = 0; goto fixup; } getDOT(); /* * Use the visual undo buffer to store the global * string for command mode, since it is idle right now. */ oglobp = globp; CP(vutmp, genbuf+1); globp = vutmp; doinit: esave[0] = 0; fixech(); /* * Have to finagle around not to lose last * character after this command (when run from ex * command mode). This is clumsy. */ d = peekc; ungetchar(0); if (shouldpo) { /* * So after a "Hit return..." ":", we do * another "Hit return..." the next time */ pofix(); shouldpo = 0; } CATCH /* * Save old values of options so we can * notice when they change; switch into * cooked mode so we are interruptible. */ onumber = value(NUMBER); olist = value(LIST); OPline = Pline; OPutchar = Putchar; commands(1, 1); if (dot == zero && dol > zero) dot = one; ONERR copy(esave, vtube[WECHO], TUBECOLS * sizeof *esave); ENDCATCH fixol(); Pline = OPline; Putchar = OPutchar; ungetchar(d); if (globp && tflag < 0) { tflag = 0; goto doinit; } globp = oglobp; /* * If we ended up with no lines in the buffer, make * a line, and don't consider the buffer changed. */ if (dot == zero) { fixzero(); /*synced();*/ } splitw = 0; /* * Special case: did list/number options change? */ if (onumber != value(NUMBER)) setnumb(value(NUMBER)); if (olist != value(LIST)) setlist(value(LIST)); fixup: /* * If a change occurred, other than * a write which clears changes, then * we should allow an undo even if . * didn't move. * * BUG: You can make this wrong by * tricking around with multiple commands * on one line of : escape, and including * a write command there, but its not * worth worrying about. */ if (FIXUNDO && tchng && tchng != i) vundkind = VMANY, cursor = 0; /* * If we are about to do another :, hold off * updating of screen. */ if (vcnt < 0 && Peekkey == ':') { getDOT(); shouldpo = 1; continue; } shouldpo = 0; /* * In the case where the file being edited is * new; e.g. if the initial state hasn't been * saved yet, then do so now. */ if (unddol == truedol) { vundkind = VNONE; Vlines = lineDOL(); if (!inglobal) savevis(); addr = zero; vcnt = 0; if (esave[0] == 0) copy(esave, vtube[WECHO], TUBECOLS * sizeof *esave); } /* * If the current line moved reset the cursor position. */ if (dot != addr) { vmoving = 0; cursor = 0; } /* * If current line is not on screen or if we are * in open mode and . moved, then redraw. */ i = vcline + (dot - addr); if (i < 0 || i >= vcnt && i >= -vcnt || state != VISUAL && dot != addr) { if (state == CRTOPEN) vup1(); if (vcnt > 0) vcnt = 0; vjumpto(dot, (char *) 0, '.'); } else { /* * Current line IS on screen. * If we did a [Hit return...] then * restore vcnt and clear screen if in visual */ vcline = i; if (vcnt < 0) { vcnt = -vcnt; if (state == VISUAL) vclear(); else if (state == CRTOPEN) { vcnt = 0; } } /* * Limit max value of vcnt based on $ */ i = vcline + lineDOL() - lineDOT() + 1; if (i < vcnt) vcnt = i; /* * Dirty and repaint. */ vdirty(0, TLINES); vrepaint(cursor); } /* * If in visual, put back the echo area * if it was clobberred. */ if (state == VISUAL) { int sdc = destcol, sdl = destline; splitw++; vigoto(WECHO, 0); for (i = 0; i < TUBECOLS - 1; i++) { if (esave[i] == 0) break; vputchar(esave[i]); } splitw = 0; vgoto(sdl, sdc); } continue; /* * u undo the last changing command. */ case 'u': vundo(1); continue; /* * U restore current line to initial state. */ case 'U': vUndo(); continue; fonfon: beep(); vmacp = 0; inopen = 1; /* might have been -1 */ continue; } /* * Rest of commands are decoded by the operate * routine. */ operate(c, cnt); } }
/* * Decode an operator/operand type command. * Eventually we switch to an operator subroutine in ex_vops.c. * The work here is setting up a function variable to point * to the routine we want, and manipulation of the variables * wcursor and wdot, which mark the other end of the affected * area. If wdot is zero, then the current line is the other end, * and if wcursor is zero, then the first non-blank location of the * other line is implied. */ void operate(register int c, register int cnt) { register int i = 0; void (*moveop)(int), (*deleteop)(int); void (*opf)(int); bool subop = 0; char *oglobp, *ocurs; register line *addr; line *odot; static int lastFKND, lastFCHR; short d; cell nullcell[1], qmarkcell[2], slashcell[2]; CLOBBGRD(opf); CLOBBGRD(d); qmarkcell[0] = '?'; slashcell[0] = '/'; nullcell[0] = qmarkcell[1] = slashcell[1] = 0; moveop = vmove, deleteop = vdelete; wcursor = cursor; wdot = NOLINE; notecnt = 0; dir = 1; switch (c) { /* * d delete operator. */ case 'd': moveop = vdelete; deleteop = (void (*)(int))beep; break; /* * s substitute characters, like c\040, i.e. change space. */ case 's': ungetkey(' '); subop++; /* fall into ... */ /* * c Change operator. */ case 'c': if (c == 'c' && workcmd[0] == 'C' || workcmd[0] == 'S') subop++; moveop = vchange; deleteop = (void (*)(int))beep; break; /* * ! Filter through a UNIX command. */ case '!': moveop = vfilter; deleteop = (void (*)(int))beep; break; /* * y Yank operator. Place specified text so that it * can be put back with p/P. Also yanks to named buffers. */ case 'y': moveop = vyankit; deleteop = (void (*)(int))beep; break; /* * = Reformat operator (for LISP). */ #ifdef LISPCODE case '=': forbid(!value(LISP)); /* fall into ... */ #endif /* * > Right shift operator. * < Left shift operator. */ case '<': case '>': moveop = vshftop; deleteop = (void (*)(int))beep; break; /* * r Replace character under cursor with single following * character. */ case 'r': vmacchng(1); vrep(cnt); return; default: goto nocount; } vmacchng(1); /* * Had an operator, so accept another count. * Multiply counts together. */ if (xisdigit(peekkey()) && peekkey() != '0') { cnt *= vgetcnt(); Xcnt = cnt; forbid (cnt <= 0); } /* * Get next character, mapping it and saving as * part of command for repeat. */ c = map(getesc(),arrows); if (c == 0) return; if (!subop) *lastcp++ = c; nocount: opf = moveop; switch (c) { /* * b Back up a word. * B Back up a word, liberal definition. */ case 'b': case 'B': dir = -1; /* fall into ... */ /* * w Forward a word. * W Forward a word, liberal definition. */ case 'W': case 'w': wdkind = c & ' '; forbid(llfind(2, cnt, opf, 0) < 0); vmoving = 0; break; /* * E to end of following blank/nonblank word */ case 'E': wdkind = 0; goto ein; /* * e To end of following word. */ case 'e': wdkind = 1; ein: forbid(llfind(3, cnt - 1, opf, 0) < 0); vmoving = 0; break; /* * ( Back an s-expression. */ case '(': dir = -1; /* fall into... */ /* * ) Forward an s-expression. */ case ')': forbid(llfind(0, cnt, opf, (line *) 0) < 0); markDOT(); break; /* * { Back an s-expression, but don't stop on atoms. * In text mode, a paragraph. For C, a balanced set * of {}'s. */ case '{': dir = -1; /* fall into... */ /* * } Forward an s-expression, but don't stop on atoms. * In text mode, back paragraph. For C, back a balanced * set of {}'s. */ case '}': forbid(llfind(1, cnt, opf, (line *) 0) < 0); markDOT(); break; /* * % To matching () or {}. If not at ( or { scan for * first such after cursor on this line. */ case '%': vsave(); i = lmatchp((line *) 0); #ifdef TRACE if (trace) fprintf(trace, "after lmatchp in %, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); #endif getDOT(); forbid(!i); if (opf != vmove) if (dir > 0) wcursor += skipright(linebuf, wcursor); else cursor += skipright(linebuf, cursor); else markDOT(); vmoving = 0; break; /* * [ Back to beginning of defun, i.e. an ( in column 1. * For text, back to a section macro. * For C, back to a { in column 1 (~~ beg of function.) */ case '[': dir = -1; /* fall into ... */ /* * ] Forward to next defun, i.e. a ( in column 1. * For text, forward section. * For C, forward to a } in column 1 (if delete or such) * or if a move to a { in column 1. */ case ']': if (!vglobp) forbid(getkey() != c); forbid (Xhadcnt); vsave(); i = lbrack(c, opf); getDOT(); forbid(!i); markDOT(); if (ospeed > B300) hold |= HOLDWIG; break; /* * , Invert last find with f F t or T, like inverse * of ;. */ case ',': forbid (lastFKND == 0); c = xisupper(lastFKND&TRIM) ? xtolower(lastFKND&TRIM) : xtoupper(lastFKND&TRIM); i = lastFCHR; if (vglobp == 0) vglobp = nullcell; subop++; goto nocount; /* * 0 To beginning of real line. */ case '0': wcursor = linebuf; vmoving = 0; break; /* * ; Repeat last find with f F t or T. */ case ';': forbid (lastFKND == 0); c = lastFKND; i = lastFCHR; subop++; goto nocount; /* * F Find single character before cursor in current line. * T Like F, but stops before character. */ case 'F': /* inverted find */ case 'T': dir = -1; /* fall into ... */ /* * f Find single character following cursor in current line. * t Like f, but stope before character. */ case 'f': /* find */ case 't': if (!subop) { i = getesc(); if (i == 0) return; *lastcp++ = i; } if (vglobp == 0) lastFKND = c, lastFCHR = i; for (; cnt > 0; cnt--) forbid (find(i) == 0); vmoving = 0; switch (c) { case 'T': wcursor += skipright(linebuf, wcursor); break; case 't': wcursor += skipleft(linebuf, wcursor); case 'f': fixup: if (moveop != vmove) wcursor += skipright(linebuf, wcursor); break; } break; /* * | Find specified print column in current line. */ case '|': if (Pline == numbline) cnt += 8; vmovcol = cnt; vmoving = 1; wcursor = vfindcol(cnt); break; /* * ^ To beginning of non-white space on line. */ case '^': wcursor = vskipwh(linebuf); vmoving = 0; break; /* * $ To end of line. */ case '$': if (opf == vmove) { vmoving = 1; vmovcol = 20000; } else vmoving = 0; if (cnt > 1) { if (opf == vmove) { wcursor = 0; cnt--; } else wcursor = linebuf; /* This is wrong at EOF */ wdot = dot + cnt; break; } if (linebuf[0]) { wcursor = strend(linebuf) - 1; goto fixup; } wcursor = linebuf; break; /* * h Back a character. * ^H Back a character. */ case 'h': case CTRL('h'): dir = -1; /* fall into ... */ /* * space Forward a character. */ case 'l': case ' ': forbid (margin() || opf == vmove && edge()); while (cnt > 0 && !margin()) { wcursor += dir>0 ? skipright(linebuf, wcursor) : skipleft(linebuf, wcursor); cnt--; } if (margin() && opf == vmove || wcursor < linebuf) wcursor -= dir; vmoving = 0; break; /* * D Delete to end of line, short for d$. */ case 'D': cnt = INF; goto deleteit; /* * X Delete character before cursor. */ case 'X': dir = -1; /* fall into ... */ deleteit: /* * x Delete character at cursor, leaving cursor where it is. */ case 'x': if (margin()) goto errlab; vmacchng(1); while (cnt > 0 && !margin()) { wcursor += dir > 0 ? skipright(linebuf, wcursor) : skipleft(linebuf, wcursor); cnt--; } opf = deleteop; vmoving = 0; break; default: /* * Stuttered operators are equivalent to the operator on * a line, thus turn dd into d_. */ if (opf == vmove || c != workcmd[0]) { errlab: beep(); vmacp = 0; return; } /* fall into ... */ /* * _ Target for a line or group of lines. * Stuttering is more convenient; this is mostly * for aesthetics. */ case '_': wdot = dot + cnt - 1; vmoving = 0; wcursor = 0; break; /* * H To first, home line on screen. * Count is for count'th line rather than first. */ case 'H': wdot = (dot - vcline) + cnt - 1; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * - Backwards lines, to first non-white character. */ case '-': wdot = dot - cnt; vmoving = 0; wcursor = 0; break; /* * ^P To previous line same column. Ridiculous on the * console of the VAX since it puts console in LSI mode. */ case 'k': case CTRL('p'): wdot = dot - cnt; if (vmoving == 0) vmoving = 1, vmovcol = lcolumn(cursor); wcursor = 0; break; /* * L To last line on screen, or count'th line from the * bottom. */ case 'L': wdot = dot + vcnt - vcline - cnt; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * M To the middle of the screen. */ case 'M': wdot = dot + ((vcnt + 1) / 2) - vcline - 1; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * + Forward line, to first non-white. * * CR Convenient synonym for +. */ case '+': case CR: wdot = dot + cnt; vmoving = 0; wcursor = 0; break; /* * ^N To next line, same column if possible. * * LF Linefeed is a convenient synonym for ^N. */ case CTRL('n'): case 'j': case NL: wdot = dot + cnt; if (vmoving == 0) vmoving = 1, vmovcol = lcolumn(cursor); wcursor = 0; break; /* * n Search to next match of current pattern. */ case 'n': vglobp = vscandir; c = *vglobp++; goto nocount; /* * N Like n but in reverse direction. */ case 'N': vglobp = vscandir[0] == '/' ? qmarkcell : slashcell; c = *vglobp++; goto nocount; /* * ' Return to line specified by following mark, * first white position on line. * * ` Return to marked line at remembered column. */ case '\'': case '`': d = c; c = getesc(); if (c == 0) return; c = markreg(c); forbid (c == 0); wdot = getmark(c); forbid (wdot == NOLINE); forbid (Xhadcnt); vmoving = 0; wcursor = d == '`' ? ncols[c - 'a'] : 0; if (opf == vmove && (wdot != dot || (d == '`' && wcursor != cursor))) markDOT(); if (wcursor) { vsave(); getline(*wdot); if (wcursor > strend(linebuf)) wcursor = 0; getDOT(); } if (ospeed > B300) hold |= HOLDWIG; break; /* * G Goto count'th line, or last line if no count * given. */ case 'G': if (!Xhadcnt) cnt = lineDOL(); wdot = zero + cnt; forbid (wdot < one || wdot > dol); if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * / Scan forward for following re. * ? Scan backward for following re. */ case '/': case '?': forbid (Xhadcnt); vsave(); ocurs = cursor; odot = dot; wcursor = 0; if (readecho(c)) return; if (!vglobp) vscandir[0] = genbuf[0]; oglobp = globp; CP(vutmp, genbuf); globp = vutmp; d = peekc; fromsemi: ungetchar(0); fixech(); CATCH addr = address(cursor); ONERR slerr: globp = oglobp; dot = odot; cursor = ocurs; ungetchar(d); splitw = 0; vclean(); vjumpto(dot, ocurs, 0); return; ENDCATCH if (globp == 0) globp = ""; else if (peekc) --globp; if (*globp == ';') { /* /foo/;/bar/ */ globp++; dot = addr; cursor = loc1; goto fromsemi; } dot = odot; ungetchar(d); c = 0; if (*globp == 'z') globp++, c = '\n'; if (any(*globp, "^+-.")) c = *globp++; i = 0; while (xisdigit(*globp&TRIM)) i = i * 10 + *globp++ - '0'; if (any(*globp, "^+-.")) c = *globp++; if (*globp) { /* random junk after the pattern */ beep(); goto slerr; } globp = oglobp; splitw = 0; vmoving = 0; wcursor = loc1; if (i != 0) vsetsiz(i); if (opf == vmove) { if (state == ONEOPEN || state == HARDOPEN) outline = destline = WBOT; if (addr != dot || loc1 != cursor) markDOT(); if (loc1 > linebuf && *loc1 == 0) loc1--; if (c) vjumpto(addr, loc1, c); else { vmoving = 0; if (loc1) { vmoving++; vmovcol = column(loc1); } getDOT(); if (state == CRTOPEN && addr != dot) vup1(); vupdown(addr - dot, NOSTR); } return; } lastcp[-1] = 'n'; getDOT(); wdot = addr; break; } /* * Apply. */ if (vreg && wdot == 0) wdot = dot; (*opf)(c); wdot = NOLINE; }
/* * Convert a string to a int64 integer. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ int64_t strtoll (const char *nptr, char **endptr, int base) { register const char *s = nptr; register u_int64_t acc; register int c; register u_int64_t cutoff; register int neg = 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ do { c = *s++; } while (xisspace(c)); if (c == '-') { neg = 1; c = *s++; } else if (c == '+') c = *s++; if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for longs is * [-2147483648..2147483647] and the input base is 10, * cutoff will be set to 214748364 and cutlim to either * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated * a value > 214748364, or equal but the next digit is > 7 (or 8), * the number is too big, and we will return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ cutoff = neg ? -(u_int64_t) INT64_MIN : INT64_MAX; cutlim = cutoff % (u_int64_t) base; cutoff /= (u_int64_t) base; for (acc = 0, any = 0;; c = *s++) { if (xisdigit(c)) c -= '0'; else if (xisalpha(c)) c -= xisupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = neg ? INT64_MIN : INT64_MAX; errno = ERANGE; } else if (neg) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return acc; }
/* * Attempt to parse the request line. * * This will set the values in hmsg that it determines. One may end up * with a partially-parsed buffer; the return value tells you whether * the values are valid or not. * * @return 1 if parsed correctly, 0 if more is needed, -1 if error * * TODO: * * have it indicate "error" and "not enough" as two separate conditions! * * audit this code as off-by-one errors are probably everywhere! */ int httpMsgParseRequestLine(HttpMsgBuf * hmsg) { int i = 0; int retcode; int maj = -1, min = -1; int last_whitespace = -1, line_end = -1; const char *t; /* Find \r\n - end of URL+Version (and the request) */ t = memchr(hmsg->buf, '\n', hmsg->size); if (!t) { retcode = 0; goto finish; } /* XXX this should point to the -end- of the \r\n, \n, etc. */ hmsg->req_end = t - hmsg->buf; i = 0; /* Find first non-whitespace - beginning of method */ for (; i < hmsg->req_end && (xisspace(hmsg->buf[i])); i++); if (i >= hmsg->req_end) { retcode = 0; goto finish; } hmsg->m_start = i; hmsg->req_start = i; hmsg->r_len = hmsg->req_end - hmsg->req_start + 1; /* Find first whitespace - end of method */ for (; i < hmsg->req_end && (!xisspace(hmsg->buf[i])); i++); if (i >= hmsg->req_end) { retcode = -1; goto finish; } hmsg->m_end = i - 1; hmsg->m_len = hmsg->m_end - hmsg->m_start + 1; /* Find first non-whitespace - beginning of URL+Version */ for (; i < hmsg->req_end && (xisspace(hmsg->buf[i])); i++); if (i >= hmsg->req_end) { retcode = -1; goto finish; } hmsg->u_start = i; /* Find \r\n or \n - thats the end of the line. Keep track of the last whitespace! */ for (; i <= hmsg->req_end; i++) { /* If \n - its end of line */ if (hmsg->buf[i] == '\n') { line_end = i; break; } /* we know for sure that there is at least a \n following.. */ if (hmsg->buf[i] == '\r' && hmsg->buf[i + 1] == '\n') { line_end = i; break; } /* If its a whitespace, note it as it'll delimit our version */ if (hmsg->buf[i] == ' ' || hmsg->buf[i] == '\t') { //"add for leakan: ' ' before '\n'" #ifdef CC_FRAMEWORK while(hmsg->buf[i] == ' ' || hmsg->buf[i] == '\t') i++; if((hmsg->buf[i] == '\n') || (hmsg->buf[i] == '\r' && hmsg->buf[i + 1] == '\n')) continue; last_whitespace = --i; #else last_whitespace = i; #endif } } if (i > hmsg->req_end) { retcode = -1; goto finish; } /* At this point we don't need the 'i' value; so we'll recycle it for version parsing */ /* * At this point: line_end points to the first eol char (\r or \n); * last_whitespace points to the last whitespace char in the URL. * We know we have a full buffer here! */ if (last_whitespace == -1) { maj = 0; min = 9; hmsg->u_end = line_end - 1; assert(hmsg->u_end >= hmsg->u_start); } else { /* Find the first non-whitespace after last_whitespace */ /* XXX why <= vs < ? I do need to really re-audit all of this .. */ for (i = last_whitespace; i <= hmsg->req_end && xisspace(hmsg->buf[i]); i++); if (i > hmsg->req_end) { retcode = -1; goto finish; } /* is it http/ ? if so, we try parsing. If not, the URL is the whole line; version is 0.9 */ if (i + 5 >= hmsg->req_end || (strncasecmp(&hmsg->buf[i], "HTTP/", 5) != 0)) { maj = 0; min = 9; hmsg->u_end = line_end - 1; assert(hmsg->u_end >= hmsg->u_start); } else { /* Ok, lets try parsing! Yes, this needs refactoring! */ hmsg->v_start = i; i += 5; /* next should be 1 or more digits */ maj = 0; for (; i < hmsg->req_end && (xisdigit(hmsg->buf[i])) && maj < 65536; i++) { maj = maj * 10; maj = maj + (hmsg->buf[i]) - '0'; } if (i >= hmsg->req_end || maj >= 65536) { retcode = -1; goto finish; } /* next should be .; we -have- to have this as we have a whole line.. */ if (hmsg->buf[i] != '.') { retcode = 0; goto finish; } if (i + 1 >= hmsg->req_end) { retcode = -1; goto finish; } /* next should be one or more digits */ i++; min = 0; for (; i < hmsg->req_end && (xisdigit(hmsg->buf[i])) && min < 65536; i++) { min = min * 10; min = min + (hmsg->buf[i]) - '0'; } if (min >= 65536) { retcode = -1; goto finish; } /* Find whitespace, end of version */ hmsg->v_end = i; hmsg->v_len = hmsg->v_end - hmsg->v_start + 1; hmsg->u_end = last_whitespace - 1; } } hmsg->u_len = hmsg->u_end - hmsg->u_start + 1; /* * Rightio - we have all the schtuff. Return true; we've got enough. */ retcode = 1; assert(maj != -1); assert(min != -1); finish: hmsg->v_maj = maj; hmsg->v_min = min; debug(1, 2) ("Parser: retval %d: from %d->%d: method %d->%d; url %d->%d; version %d->%d (%d/%d)\n", retcode, hmsg->req_start, hmsg->req_end, hmsg->m_start, hmsg->m_end, hmsg->u_start, hmsg->u_end, hmsg->v_start, hmsg->v_end, maj, min); return retcode; }
static int parse_subtree(struct snmp_mib_tree *subtree, char *input, oid *output, int *out_len) { char buf[128], *to = buf; u_int subid = 0; struct snmp_mib_tree *tp; /* * No empty strings. Can happen if there is a trailing '.' or two '.'s * in a row, i.e. "..". */ if ((*input == '\0') || (*input == '.')) return (0); if (xisdigit(*input)) { /* * Read the number, then try to find it in the subtree. */ while (xisdigit(*input)) { subid *= 10; subid += *input++ - '0'; } for (tp = subtree; tp; tp = tp->next_peer) { if (tp->subid == subid) goto found; } tp = NULL; } else { /* * Read the name into a buffer. */ while ((*input != '\0') && (*input != '.')) { *to++ = *input++; } *to = '\0'; /* * Find the name in the subtree; */ for (tp = subtree; tp; tp = tp->next_peer) { if (lc_cmp(tp->label, buf) == 0) { subid = tp->subid; goto found; } } /* * If we didn't find the entry, punt... */ if (tp == NULL) { snmplib_debug(0, "sub-identifier not found: %s\n", buf); return (0); } } found: if (subid > (u_int) MAX_SUBID) { snmplib_debug(0, "sub-identifier too large: %s\n", buf); return (0); } if ((*out_len)-- <= 0) { snmplib_debug(0, "object identifier too long\n"); return (0); } *output++ = subid; if (*input != '.') return (1); if ((*out_len = parse_subtree(tp ? tp->child_list : NULL, ++input, output, out_len)) == 0) return (0); return (++*out_len); }
/* pack fields using Packer */ int httpStatusLineParse(HttpStatusLine * sline, const char *start, const char *end) { int maj, min, status; const char *s; assert(sline); sline->status = HTTP_INVALID_HEADER; /* Squid header parsing error */ if (strncasecmp(start, "HTTP/", 5)) return 0; start += 5; if (!xisdigit(*start)) return 0; /* Format: HTTP/x.x <space> <status code> <space> <reason-phrase> CRLF */ s = start; maj = 0; for (s = start; s < end && xisdigit(*s) && maj < 65536; s++) { maj = maj * 10; maj = maj + *s - '0'; } if (s >= end || maj >= 65536) { debug(57, 7) ("httpStatusLineParse: Invalid HTTP reply status major.\n"); return 0; } /* next should be '.' */ if (*s != '.') { debug(57, 7) ("httpStatusLineParse: Invalid HTTP reply status line.\n"); return 0; } s++; /* next should be minor number */ min = 0; for (; s < end && xisdigit(*s) && min < 65536; s++) { min = min * 10; min = min + *s - '0'; } if (s >= end || min >= 65536) { debug(57, 7) ("httpStatusLineParse: Invalid HTTP reply status version minor.\n"); return 0; } /* then a space */ if (*s != ' ') { } s++; /* next should be status start */ status = 0; for (; s < end && xisdigit(*s); s++) { status = status * 10; status = status + *s - '0'; } if (s >= end) { debug(57, 7) ("httpStatusLineParse: Invalid HTTP reply status code.\n"); return 0; } /* then a space */ /* for now we ignore the reason-phrase */ /* then crlf */ sline->version.major = maj; sline->version.minor = min; sline->status = status; /* we ignore 'reason-phrase' */ return 1; /* success */ }