Esempio n. 1
0
File: lexer.c Progetto: Saruta/a2c
struct token *gettok()
{
  struct token *tok = malloc(sizeof(struct token));
  tok->pos = malloc(sizeof(struct pos));
  char c = nextnonblank();
  tok->pos->line = curline;
  tok->pos->charstart = curchar;
  if (c != '\n')
    ungetc(c, fin);
  if (isdigit(c))
    getnum(tok);
  else if (isalnum(c))
    getalnum(tok);
  else if (c == '\'')
  {
    getc(fin);
    c = getc(fin);
    tok->type = CHAR;
    tok->val = malloc(3);
    tok->val[0] = tok->val[2] = '\'';
    tok->val[1] = c;
    c = getc(fin);
    if (c != '\'')
    {
      tok->pos->len = 2;
      error(*tok->pos, "missing ' to end character");
    }
  }
  else if (c == '\"')
    getstring(tok);
  else if (c == EOF)
  {
    tok->type = ENDOFFILE;
    tok->val = "EOF";
  }
  else if (c == '\n')
  {
    tok->type = EOL;
    tok->val = "EOL";
  }
  else
    getop(tok);
  tok->pos->len = curchar - tok->pos->charstart;
  return tok;
}
Esempio n. 2
0
File: altsvc.c Progetto: curl/curl
/*
 * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
 * the data correctly in the cache.
 *
 * 'value' points to the header *value*. That's contents to the right of the
 * header name.
 */
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
                           struct altsvcinfo *asi, const char *value,
                           enum alpnid srcalpnid, const char *srchost,
                           unsigned short srcport)
{
  const char *p = value;
  size_t len;
  enum alpnid dstalpnid = srcalpnid; /* the same by default */
  char namebuf[MAX_ALTSVC_HOSTLEN] = "";
  char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
  struct altsvc *as;
  unsigned short dstport = srcport; /* the same by default */
  const char *semip;
  time_t maxage = 24 * 3600; /* default is 24 hours */
  bool persist = FALSE;
  CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
  if(result)
    return result;

  DEBUGASSERT(asi);

  /* Flush all cached alternatives for this source origin, if any */
  altsvc_flush(asi, srcalpnid, srchost, srcport);

  /* "clear" is a magic keyword */
  if(strcasecompare(alpnbuf, "clear")) {
    /* TODO: clear whatever it is it should clear */
    return CURLE_OK;
  }

  /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
     but are set after the list on the line. Scan for the semicolons and get
     those fields first! */
  semip = p;
  do {
    semip = strchr(semip, ';');
    if(semip) {
      char option[32];
      unsigned long num;
      char *end_ptr;
      semip++; /* pass the semicolon */
      result = getalnum(&semip, option, sizeof(option));
      if(result)
        break;
      while(*semip && ISBLANK(*semip))
        semip++;
      if(*semip != '=')
        continue;
      semip++;
      num = strtoul(semip, &end_ptr, 10);
      if(num < ULONG_MAX) {
        if(strcasecompare("ma", option))
          maxage = num;
        else if(strcasecompare("persist", option) && (num == 1))
          persist = TRUE;
      }
      semip = end_ptr;
    }
  } while(semip);

  do {
    if(*p == '=') {
      /* [protocol]="[host][:port]" */
      dstalpnid = alpn2alpnid(alpnbuf);
      if(!dstalpnid) {
        infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
        return CURLE_OK;
      }
      p++;
      if(*p == '\"') {
        const char *dsthost;
        p++;
        if(*p != ':') {
          /* host name starts here */
          const char *hostp = p;
          while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
            p++;
          len = p - hostp;
          if(!len || (len >= MAX_ALTSVC_HOSTLEN))
            return CURLE_BAD_FUNCTION_ARGUMENT; /* TODO: improve error code */
          memcpy(namebuf, hostp, len);
          namebuf[len] = 0;
          dsthost = namebuf;
        }
        else {
          /* no destination name, use source host */
          dsthost = srchost;
        }
        if(*p == ':') {
          /* a port number */
          char *end_ptr;
          unsigned long port = strtoul(++p, &end_ptr, 10);
          if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
            infof(data, "Unknown alt-svc port number, ignoring...\n");
            return CURLE_OK;
          }
          p = end_ptr;
          dstport = curlx_ultous(port);
        }
        if(*p++ != '\"')
          return CURLE_BAD_FUNCTION_ARGUMENT;
        as = altsvc_createid(srchost, dsthost,
                             srcalpnid, dstalpnid,
                             srcport, dstport);
        if(as) {
          /* TODO: the expires time also needs to take the Age: value (if any)
             into account. [See RFC 7838 section 3.1] */
          as->expires = maxage + time(NULL);
          as->persist = persist;
          Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
          asi->num++; /* one more entry */
          infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
                Curl_alpnid2str(dstalpnid));
        }
      }
      /* after the double quote there can be a comma if there's another
         string or a semicolon if no more */
      if(*p == ',') {
        /* comma means another alternative is presented */
        p++;
        result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
        if(result)
          /* failed to parse, but since we already did at least one host we
             return OK */
          return CURLE_OK;
      }
    }
  } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));

  return CURLE_OK;
}