Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 4
0
/* 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
    );
}
Esempio n. 5
0
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;
}
Esempio n. 6
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@*/
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
/* 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);
}
Esempio n. 9
0
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;
  }
}
Esempio n. 10
0
/* 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;
}
Esempio n. 12
0
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 */
}
Esempio n. 14
0
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);
}
Esempio n. 15
0
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;
}
Esempio n. 16
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;
}
Esempio n. 17
0
/*
** 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 */
Esempio n. 18
0
/*
 * 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
Esempio n. 19
0
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);
}
Esempio n. 20
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¶æ,
 */
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;
}
Esempio n. 21
0
File: vars.c Progetto: porridge/ekg
/*
 * 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;
}
Esempio n. 22
0
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);
}
}
Esempio n. 23
0
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;
}
Esempio n. 24
0
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;
}
Esempio n. 25
0
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);
	}
}
Esempio n. 26
0
/*
 * 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;
}
Esempio n. 27
0
/*
 * 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;
}
Esempio n. 28
0
/*
 * 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;
}
Esempio n. 29
0
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);
}
Esempio n. 30
0
/* 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 */
}