Esempio n. 1
0
void s3d_fnt_load_info(s3d_fnt_info *info, const char *path) {
    {
        info->line_height = -1;
        info->chars = 0;
    }

    int ichar = -1;

    static char path_buf[PATH_MAX];

    s3d_strarrjoin(path_buf, { path, "/info" });

    char *lines = s3d_read_file(path_buf, 1, 0);

    s3d_streachline(lines, line, line_no, {
        char *lptr = line;

        #define abort_parse(message, more...) \
            abort_because( \
                "%s:%d: " message ": %s", \
                path_buf, line_no, ##more, line \
            )

        #define parse_tag(name) s3d_strconsume(&lptr, name " ")

        #define parse_attr_tok(name) { \
            s3d_strskip(&lptr, " "); \
            \
            if(!s3d_strconsume(&lptr, name "=")) { \
                abort_parse("Expected '" name "=' token"); \
            } \
        }

        #define parse_tok(tok) \
            s3d_strskip(&lptr, " "); \
            \
            if(!s3d_strconsume(&lptr, tok)) { \
                abort_parse("Expected '" tok "' token"); \
            }

        #define parse_long(dst, name) { \
            errno = 0; \
            \
            dst = strtol(lptr, &lptr, 10); \
            \
            if(errno) { \
                abort_parse("Bad " name " value"); \
            } \
        }

        #define parse_eol() \
            if(!s3d_strempty(lptr)) { \
                abort_parse("Trailing characters"); \
            }

        if(parse_tag("common")) {
            parse_attr_tok("lineHeight");
            parse_long(info->line_height, "line height");

            parse_attr_tok("base");
            parse_long(info->base, "base");

            parse_attr_tok("scaleW");
            parse_long(info->scale_w, "scale width");

            parse_attr_tok("scaleH");
            parse_long(info->scale_h, "scale height");

            parse_tok("pages=1");
            parse_tok("packed=0");
            parse_tok("alphaChnl=1");
            parse_tok("redChnl=4");
            parse_tok("greenChnl=4");
            parse_tok("blueChnl=4");

            parse_eol();
        }
        else
        if(parse_tag("chars")) {
            parse_attr_tok("count");
            parse_long(info->num_chars, "char count");

            parse_eol();

            if(info->num_chars > 0) {
                s3d_mallocptr(info->chars, info->num_chars);
            }

            ichar = 0;
        }
        else
        if(parse_tag("char")) {
            if(ichar == -1) {
                abort_parse("char tag before chars tag");
            }

            if(ichar >= info->num_chars) {
                abort_parse(
                    "Too many char tags (more than %d)", info->num_chars
                );
            }

            s3d_fnt_char_info *cptr = &info->chars[ichar];

            parse_attr_tok("id");
            parse_long(cptr->id, "ID");

            parse_attr_tok("x");
            parse_long(cptr->x, "X");

            parse_attr_tok("y");
            parse_long(cptr->y, "Y");

            parse_attr_tok("width");
            parse_long(cptr->w, "width");

            parse_attr_tok("height");
            parse_long(cptr->h, "height");

            parse_attr_tok("xoffset");
            parse_long(cptr->xoff, "X offset");

            parse_attr_tok("yoffset");
            parse_long(cptr->yoff, "Y offset");

            parse_attr_tok("xadvance");
            parse_long(cptr->xadv, "X advance");

            parse_tok("page=0");
            parse_tok("chnl=15");

            parse_eol();

            ++ichar;
        }
        else {
            abort_parse("Invalid tag");
        }
    })

    #undef parse_tag
    #undef parse_attr_tok
    #undef parse_tok
    #undef parse_long
    #undef parse_eol

    #undef abort_parse

    if(info->line_height == -1) {
Esempio n. 2
0
int init_globals(char *config_file) {

  FILE *in_config;
  char buf[1][30], **ptr1;
  char line[MAX_LINE];
  char space[4] = "\n\t ";
  char *token;
  int err = 0;
  
#ifdef _PRINT  
  fprintf(log_file, "ENTER[init_globals].\n");
#endif
 
  in_config = fopen(config_file, "r");
  if (in_config == NULL) {
    fprintf(stderr, 
	    "Cannot open configuration file=[%s]:[%s]. Exiting.\n", config_file, strerror(errno)); 
    return 1;
  }
  
  ptr1 = (char **)&buf[0];
  while (fgets(line, MAX_LINE, in_config) != NULL) {
    fprintf(stderr, "%s\n", line); 
    if (line[0] == '#' || line[0] == '\n' || line[0] == ' ')  continue;

#if !defined (UNIX) && !defined (OSX)
	token = strtok_s(line, space, ptr1);
#else
	token = strtok_r(line, space, ptr1);
#endif
    if (!strncmp(token, "DIFFUSION_COEFFICIENT", strlen("DIFFUSION_COEFFICIENT"))) {
	  //token = strtok_s(NULL,space,ptr1);
	  err = parse_tok(ptr1,&token,space);
      e.diffusion_coefficient = strtod(token, NULL);
      /* DIFFUSION_COEFFICIENT can never be 0 as it is used in divisions */
      if (e.diffusion_coefficient < 1.0) e.diffusion_coefficient = 1.0;
      fprintf(stderr, "DIFFUSION_COEFFICIENT=%.0f\n", e.diffusion_coefficient);
    } 
    else if (!strncmp(token, "EDDY_CONST", strlen("EDDY_CONST"))) {
      //token = strtok_r(NULL,space,ptr1);
	  err = parse_tok(ptr1,&token,space);
      e.eddy_constant = strtod(token, NULL);
      fprintf(stderr, "EDDY_CONST=%.2f\n", e.eddy_constant);
    }
    else if (!strncmp(token, "FALL_TIME_THRESHOLD", strlen("FALL_TIME_THRESHOLD"))) {
      //token = strtok_r(NULL,space,ptr1);
      err = parse_tok(ptr1,&token,space);
	  e.fall_time_threshold = strtod(token, NULL);
      fprintf(stderr, "FALL_TIME_THRESHOLD=%.0f\n", e.fall_time_threshold);
    }
    else if (!strncmp(token, "LITHIC_DENSITY", strlen("LITHIC_DENSITY"))) {
      //token = strtok_r(NULL,space,ptr1);
	  err = parse_tok(ptr1,&token,space);
      e.lithic_density = strtod(token, NULL);
      fprintf(stderr, "LITHIC_DENSITY=%.0f\n", e.lithic_density);
    }
    else if (!strncmp(token, "PUMICE_DENSITY", strlen("PUMICE_DENSITY"))) {
      //token = strtok_r(NULL,space,ptr1);
      err = parse_tok(ptr1,&token,space);
      e.pumice_density = strtod(token, NULL);
      fprintf(stderr, "PUMICE_DENSITY=%.0f\n", e.pumice_density);
    }
    else if (!strncmp(token, "PART_STEPS", strlen("PART_STEPS"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      PART_STEPS = (int)atof(token);
      fprintf(stderr, "PART_STEPS = %d\n", PART_STEPS);
    }
    else if (!strncmp(token, "COL_STEPS", strlen("COL_STEPS"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      COL_STEPS = (int)atof(token);
      fprintf(stderr, "COL_STEPS = %d\n", COL_STEPS);
    }
    else if (!strncmp(token, "PLUME_MODEL", strlen("PLUME_MODEL"))) {
      //token = strtok_r(NULL,space,ptr1);
      err = parse_tok(ptr1,&token,space);
      e.plume_model = (int)atof(token);
      
      if (e.plume_model == 0) {
	      pdf = plume_pdf0;
	      fprintf(stderr, "PLUME_MODEL=[%d]%s\n", e.plume_model, "Uniform Distribution with threshold");
      }
      else if (e.plume_model == 1) {
	      pdf = plume_pdf1;
	      fprintf(stderr, "PLUME_MODEL=[%d]%s\n", e.plume_model, "log-normal Distribution using beta");
      }
      else if (e.plume_model == 2) {
	      pdf = plume_pdf2;
	      fprintf(log_file, "PLUME_MODEL=[%d]%s\n", e.plume_model, "Beta Distribution with ALPHA and BETA parameteres");
      }
    }
    else if (!strncmp(token, "PLUME_RATIO", strlen("PLUME_RATIO"))) {
      //token = strtok_r(NULL, space, ptr1);
	  err = parse_tok(ptr1,&token,space);
      e.plume_ratio = strtod(token, NULL);
      if (!e.plume_model) fprintf(stderr, "PLUME_RATIO = %.2f\n", e.plume_ratio);
    }
    else if (!strncmp(token, "ALPHA", strlen("ALPHA"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.alpha = strtod(token, NULL);
      if (e.plume_model==2) fprintf(stderr, "ALPHA = %g\n", e.alpha);
    }
    else if (!strncmp(token, "BETA", strlen("BETA"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.beta = strtod(token, NULL);
      if (e.plume_model==2) fprintf(stderr, "BETA = %g\n", e.beta);
    }
    else if (!strncmp(token, "PLUME_HEIGHT", strlen("PLUME_HEIGHT"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.max_plume_elevation = strtod(token, NULL);
      fprintf(stderr, "PLUME_HEIGHT = %.0f\n", e.max_plume_elevation);
    }
    else if (!strncmp(token, "ERUPTION_MASS", strlen("ERUPTION_MASS"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.total_ash_mass = strtod(token, NULL);
      fprintf(stderr, "ERUPTION_MASS = %g\n", e.total_ash_mass);
    }
    else if (!strncmp(token, "MAX_GRAINSIZE", strlen("MAX_GRAINSIZE"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.min_phi = strtod(token, NULL);
      fprintf(stderr, "MAX_GRAINSIZE = %g (phi)\n", e.min_phi);
    }
    else if (!strncmp(token, "MIN_GRAINSIZE", strlen("MIN_GRAINSIZE"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.max_phi = strtod(token, NULL);
      fprintf(stderr, "MIN_GRAINSIZE = %g (phi)\n", e.max_phi);
    }
    else if (!strncmp(token, "MEDIAN_GRAINSIZE", strlen("MEDIAN_GRAINSIZE"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.mean_phi = strtod(token, NULL);
      fprintf(stderr, "MEDIAN_GRAINSIZE = %g (phi)\n", e.mean_phi);
    }
    else if (!strncmp(token, "STD_GRAINSIZE", strlen("STD_GRAINSIZE"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.sigma_phi = strtod(token, NULL);
      /* if (STD_GRAINSIZE < 1.0) STD_GRAINSIZE = 1.0; */
      fprintf(stderr, "STD_GRAINSIZE = %g (phi)\n", e.sigma_phi);
    }
    else if (!strncmp(token, "VENT_EASTING", strlen("VENT_EASTING"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.vent_easting = strtod(token, NULL);
      fprintf(stderr, "VENT_EASTING = %.0f\n", e.vent_easting);
    }
    else if (!strncmp(token, "VENT_NORTHING", strlen("VENT_NORTHING"))) {
      //token = strtok_r(NULL, space, ptr1); 
      err = parse_tok(ptr1,&token,space);
      e.vent_northing = strtod(token, NULL);
      fprintf(stderr, "VENT_NORTHING = %.0f\n", e.vent_northing);
    }
    else if (!strncmp(token, "VENT_ELEVATION", strlen("VENT_ELEVATION"))) {
      //token = strtok_r(NULL, space, ptr1);
      err = parse_tok(ptr1,&token,space);
      e.vent_elevation = strtod(token, NULL);
      fprintf(stderr, "VENT_ELEVATION = %.0f\n", e.vent_elevation);
    }
    else continue;
  }
  (void) fclose(in_config);
#ifdef _PRINT
  fprintf(log_file, "EXIT[init_globals].\n");
#endif

  return 0;
}
Esempio n. 3
0
/* 
 *   Process a request from our HTTP client.  The main server loop calls this
 *   when the socket has data ready to read.  
 */
int TadsHttpServerThread::process_request()
{
    StringRef *hdrs = new StringRef(1024);
    TadsHttpRequestHeader *hdr_list = 0, *hdr_tail = 0;
    TadsHttpRequest *req = 0;
    char *verb;
    size_t verb_len;
    char *resource_name;
    size_t res_name_len;
    int ok = FALSE;
    long ofs;
    char *p, *hbody;
    StringRef *body = 0;
    int overflow = FALSE;
    long hbodylen;
    const char *hcl, *hte;             /* content-length, transfer-encoding */

    /* 
     *   Read the header.  We read data into our buffer until we find a
     *   double CR-LF sequence, indicating the end of the header.  
     */
    if ((ofs = read_to_nl(hdrs, 0, 0, 4)) < 0)
        goto done;

    /* the body, if any, starts after the double line break */
    hbody = hdrs->get() + ofs;
    hbodylen = hdrs->getlen() - ofs;

    /* truncate the headers to the CR-LF-CR-LF sequence */
    hdrs->truncate(ofs - 2);

    /*
     *   Parse the main verb in the header - get the method and the resource
     *   ID.  The format is:
     *   
     *.     <space>* VERB <space>+ RESOURCE <space>+ HTTP-VERSION <CRLF>
     */
    p = hdrs->get();
    parse_tok(p, verb, verb_len);
    parse_tok(p, resource_name, res_name_len);

    /* now parse the remaining headers */
    TadsHttpRequestHeader::parse_headers(hdr_list, hdr_tail, FALSE, hdrs, 0);

    /* 
     *   Check to see if there's a message body.  There is if there's a
     *   content-length or transfer-encoding header.
     */
    hcl = hdr_list->find("content-length");
    hte = hdr_list->find("transfer-encoding");
    if (hcl != 0 || hte != 0)
    {
        /* 
         *   There's a content body.  If there's a content-length field,
         *   pre-allocate a chunk of memory, then read the number of bytes
         *   indicated.  If it's a chunked transfer, read it in pieces.  
         */
        if (hcl != 0)
        {
            /* get the length */
            long hclval = atol(hcl);

            /* if it's non-zero, read the content */
            if (hclval != 0)
            {
                /* if this exceeds the size limit, abort */
                if (upload_limit != 0 && hclval > upload_limit)
                {
                    /* set the overflow flag, discard the input, and abort */
                    overflow = TRUE;
                    read(0, 0, hclval, 5000);
                    goto done_with_upload;
                }

                /* allocate the buffer; it's initially empty */
                body = new StringRef(hclval);

                /* copy any portion of the body we've already read */
                if (hbodylen != 0)
                {
                    /* limit this to the declared size */
                    if (hbodylen > hclval)
                        hbodylen = hclval;

                    /* copy the data */
                    body->append(hbody, hbodylen);

                    /* deduct the remaining size */
                    hclval -= hbodylen;
                }

                /* read the body */
                if (hclval != 0
                    && read(body->getend(), hclval, hclval, 5000) < 0)
                {
                    send_simple(S_http_400, "text/html",
                                "Error receiving request message body");
                    goto done;
                }

                /* set the body length */
                body->addlen(hclval);
            }
        }
        else if (stricmp(hte, "chunked") == 0)
        {
            /* set up a string buffer for the content */
            const long initlen = 32000;
            body = new StringRef(hbodylen > initlen ? hbodylen : initlen);

            /* if we've already read some body text, copy it to the buffer */
            if (hbodylen != 0)
                body->append(hbody, hbodylen);
            
            /* keep going until we reach the end marker */
            for (ofs = 0 ; ; )
            {
                /* read to the first newline */
                long nlofs = read_to_nl(body, ofs, 0, 2);
                if (nlofs < 0)
                    goto done;

                /* get the chunk length */
                long chunklen = strtol(body->get() + ofs, 0, 16);

                /* 
                 *   We're done with the chunk length.  Move any read-ahead
                 *   content down in memory so that it directly abuts the
                 *   preceding chunk, so that when we're done we'll have the
                 *   content assembled into one contiguous piece.  
                 */
                long ralen = body->getlen() - nlofs;
                if (ralen > 0)
                    memmove(body->get() + ofs, body->get() + nlofs,
                            body->getlen() - nlofs);

                /* stop at the end of the read-ahead portion */
                body->truncate(ofs + ralen);

                /* if the chunk length is zero, we're done */
                if (chunklen == 0)
                    break;

                /* check if this would overflow our upload size limit */
                if (upload_limit != 0
                    && !overflow
                    && body->getlen() + chunklen > upload_limit)
                {
                    /* flag the overflow, but keep reading the content */
                    overflow = TRUE;
                }

                /* 
                 *   figure the remaining read size for this chunk, after any
                 *   read-ahead portion 
                 */
                long chunkrem = chunklen - ralen;

                /* 
                 *   if we've already overflowed, read and discard the chunk;
                 *   otherwise read it into our buffer 
                 */
                if (chunkrem + 2 <= 0)
                {
                    /* 
                     *   We've already read ahead by enough to cover the next
                     *   chunk and the newline at the end.  Go in and delete
                     *   the newline (or as much of it as exists).  Start by
                     *   getting the offset of the newline: it's just after
                     *   the current chunk, which starts at 'ofs' and runs
                     *   for 'chunklen'.  
                     */
                    nlofs = ofs + chunklen;

                    /* 
                     *   if we haven't yet read the full newline sequence, do
                     *   so now
                     */
                    if (ralen - chunklen < 2)
                    {
                        long nllen = 2 - (ralen - chunklen);
                        body->ensure(nllen);
                        if (read(body->getend(), nllen, nllen, 30000) < 0)
                        {
                            send_simple(S_http_400, "text/html",
                                        "Error receiving request message chunk");
                            goto done;
                        }
                    }

                    /* 
                     *   if there's anything after the newline, move it down
                     *   to overwrite the newline 
                     */
                    if (ralen - chunklen > 2)
                    {
                        /* move the bytes */
                        memmove(body->get() + nlofs,
                                body->get() + nlofs + 2,
                                ralen - chunklen - 2);

                        /* adjust the size for the closed gap */
                        body->truncate(body->getlen() - 2);
                    }

                    /* resume from after the newline */
                    ofs = nlofs;
                }
                else if (overflow)
                {
                    /* overflow - discard the chunk size (plus the CR-LF) */
                    if (read(0, 0, chunkrem+2, 30000) < 0)
                        goto done;

                    /* clear the buffer */
                    body->truncate(0);
                    ofs = 0;
                }
                else
                {
                    /* ensure the buffer is big enough */
                    body->ensure(chunkrem + 2);

                    /* read the chunk, plus the CR-LF that follows */
                    if (read(body->getend(),
                             chunkrem + 2, chunkrem + 2, 30000) < 0)
                    {
                        send_simple(S_http_400, "text/html",
                                    "Error receiving request message chunk");
                        goto done;
                    }

                    /* count the amount we just read in the buffer length */
                    body->addlen(chunkrem + 2);

                    /* verify that the last two bytes are indeed CR-LF */
                    if (memcmp(body->getend() - 2, "\r\n", 2) != 0)
                    {
                        send_simple(S_http_400, "text/html",
                                    "Error in request message chunk");
                        goto done;
                    }

                    /* 
                     *   move past the chunk for the next read, minus the
                     *   CR-LF that follows the chunk - that isn't part of
                     *   the data, but just part of the protocol 
                     */
                    ofs = body->getlen() - 2;
                    body->truncate(ofs);
                }
            }

            /* 
             *   Read to the closing blank line.  We've just passed one
             *   newline, following the '0' end length marker, so we're in
             *   state 2.  We could have either another newline following, or
             *   "trailers" (more headers, following the content body).
             */
            long nlofs = read_to_nl(body, ofs, 2, 4);
            if (nlofs < 0)
                goto done;

            /* 
             *   if we have more than just the closing blank line, we have
             *   trailers - append them to the headers 
             */
            if (nlofs > ofs + 2)
            {
                TadsHttpRequestHeader::parse_headers(
                    hdr_list, hdr_tail, TRUE, body, ofs);
            }

            /* 
             *   the trailers (if any) and closing newline aren't part of the
             *   content - clip them out of the body 
             */
            body->truncate(ofs);
        }
        else
        {
            /* 
             *   Other combinations of these headers are illegal.  Send an
             *   error and abort. 
             */
            send_simple(S_http_400, "text/html",
                        "<html><title>Bad Request</title>"
                        "<h1>Bad Request</h1>"
                        "This server does not accept the specified "
                        "transfer-encoding.");
            goto done;
        }

    done_with_upload:
        /* done with the upload - check for overflow */
        if (overflow)
        {
            /* release the body, if present */
            if (body != 0)
            {
                body->release_ref();
                body = 0;
            }
        }
    }

    /* create a message object for the request */
    req = new TadsHttpRequest(
        this, verb, verb_len, hdrs, hdr_list, body, overflow,
        resource_name, res_name_len,
        listener->get_shutdown_evt());

    /* we've handed over the header list to the request */
    hdr_list = 0;
    
    /* send it to the main thread, and wait for the reply */
    if (queue->send(req, OS_FOREVER))
    {
        /* 
         *   success - the server will already have sent the reply, so we're
         *   done 
         */
    }
    else if (queue->is_quitting())
    {
        /* failed due to server shutdown */
        send_simple(S_http_503, "text/html", S_http_503_quitting_body);
    }
    else
    {
        /* 'send' failed - return an internal server error */
        send_simple(S_http_500, "text/html", S_http_500_body);
    }
    
    /* we're done with the request */
    req->release_ref();

    /* success */
    ok = TRUE;

done:
    /* release the message body buffer */
    if (body != 0)
        body->release_ref();

    /* release the header buffer */
    hdrs->release_ref();

    /* delete the header list */
    if (hdr_list != 0)
        delete hdr_list;

    /* return the success/failure indication */
    return ok;
}