Exemple #1
0
/**
 * Change timetable data of an order.
 * @param tile Not used.
 * @param flags Operation to perform.
 * @param p1 Various bitstuffed elements
 * - p1 = (bit  0-19) - Vehicle with the orders to change.
 * - p1 = (bit 20-27) - Order index to modify.
 * - p1 = (bit 28-29) - Timetable data to change (@see ModifyTimetableFlags)
 * @param p2 The amount of time to wait.
 * - p2 = (bit  0-15) - The data to modify as specified by p1 bits 28-29.
 *                      0 to clear times, UINT16_MAX to clear speed limit.
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
    VehicleID veh = GB(p1, 0, 20);

    Vehicle *v = Vehicle::GetIfValid(veh);
    if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;

    CommandCost ret = CheckOwnership(v->owner);
    if (ret.Failed()) return ret;

    VehicleOrderID order_number = GB(p1, 20, 8);
    Order *order = v->GetOrder(order_number);
    if (order == NULL || order->IsType(OT_IMPLICIT)) return CMD_ERROR;

    ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1);
    if (mtf >= MTF_END) return CMD_ERROR;

    int wait_time   = order->GetWaitTime();
    int travel_time = order->GetTravelTime();
    int max_speed   = order->GetMaxSpeed();
    switch (mtf) {
    case MTF_WAIT_TIME:
        wait_time = GB(p2, 0, 16);
        break;

    case MTF_TRAVEL_TIME:
        travel_time = GB(p2, 0, 16);
        break;

    case MTF_TRAVEL_SPEED:
        max_speed = GB(p2, 0, 16);
        if (max_speed == 0) max_speed = UINT16_MAX; // Disable speed limit.
        break;

    default:
        NOT_REACHED();
    }

    if (wait_time != order->GetWaitTime()) {
        switch (order->GetType()) {
        case OT_GOTO_STATION:
            if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
            break;

        case OT_CONDITIONAL:
            break;

        default:
            return_cmd_error(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
        }
    }

    if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
    if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;

    if (flags & DC_EXEC) {
        switch (mtf) {
        case MTF_WAIT_TIME:
            /* Set time if changing the value or confirming an estimated time as timetabled. */
            if (wait_time != order->GetWaitTime() || (wait_time > 0 && !order->IsWaitTimetabled())) {
                ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME, wait_time > 0);
            }
            break;

        case MTF_TRAVEL_TIME:
            /* Set time if changing the value or confirming an estimated time as timetabled. */
            if (travel_time != order->GetTravelTime() || (travel_time > 0 && !order->IsTravelTimetabled())) {
                ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME, travel_time > 0);
            }
            break;

        case MTF_TRAVEL_SPEED:
            if (max_speed != order->GetMaxSpeed()) {
                ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED, max_speed != UINT16_MAX);
            }
            break;

        default:
            break;
        }
    }

    return CommandCost();
}
Exemple #2
0
/**
 * Converts a given grayscale map to something that fits in OTTD map system
 * and create a map of that data.
 * @param img_width  the with of the image in pixels/tiles
 * @param img_height the height of the image in pixels/tiles
 * @param map        the input map
 */
static void GrayscaleToMapHeights(uint img_width, uint img_height, byte *map)
{
	/* Defines the detail of the aspect ratio (to avoid doubles) */
	const uint num_div = 16384;

	uint width, height;
	uint row, col;
	uint row_pad = 0, col_pad = 0;
	uint img_scale;
	uint img_row, img_col;
	TileIndex tile;

	/* Get map size and calculate scale and padding values */
	switch (_settings_game.game_creation.heightmap_rotation) {
		default: NOT_REACHED();
		case HM_COUNTER_CLOCKWISE:
			width   = MapSizeX();
			height  = MapSizeY();
			break;
		case HM_CLOCKWISE:
			width   = MapSizeY();
			height  = MapSizeX();
			break;
	}

	if ((img_width * num_div) / img_height > ((width * num_div) / height)) {
		/* Image is wider than map - center vertically */
		img_scale = (width * num_div) / img_width;
		row_pad = (1 + height - ((img_height * img_scale) / num_div)) / 2;
	} else {
		/* Image is taller than map - center horizontally */
		img_scale = (height * num_div) / img_height;
		col_pad = (1 + width - ((img_width * img_scale) / num_div)) / 2;
	}

	if (_settings_game.construction.freeform_edges) {
		for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
		for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
	}

	/* Form the landscape */
	for (row = 0; row < height; row++) {
		for (col = 0; col < width; col++) {
			switch (_settings_game.game_creation.heightmap_rotation) {
				default: NOT_REACHED();
				case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break;
				case HM_CLOCKWISE:         tile = TileXY(row, col); break;
			}

			/* Check if current tile is within the 1-pixel map edge or padding regions */
			if ((!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1) ||
					(row < row_pad) || (row >= (height - row_pad - (_settings_game.construction.freeform_edges ? 0 : 1))) ||
					(col < col_pad) || (col >= (width  - col_pad - (_settings_game.construction.freeform_edges ? 0 : 1)))) {
				SetTileHeight(tile, 0);
			} else {
				/* Use nearest neighbour resizing to scale map data.
				 *  We rotate the map 45 degrees (counter)clockwise */
				img_row = (((row - row_pad) * num_div) / img_scale);
				switch (_settings_game.game_creation.heightmap_rotation) {
					default: NOT_REACHED();
					case HM_COUNTER_CLOCKWISE:
						img_col = (((width - 1 - col - col_pad) * num_div) / img_scale);
						break;
					case HM_CLOCKWISE:
						img_col = (((col - col_pad) * num_div) / img_scale);
						break;
				}

				assert(img_row < img_height);
				assert(img_col < img_width);

				/* Colour scales from 0 to 255, OpenTTD height scales from 0 to 15 */
				SetTileHeight(tile, map[img_row * img_width + img_col] / 16);
			}
			/* Only clear the tiles within the map area. */
			if (IsInnerTile(tile)) {
				MakeClear(tile, CLEAR_GRASS, 3);
			}
		}
	}
}
/* The first copy is invoked without command line arguments.
   Subsequent copies are invoked with a parameter 'depth'
   that describes how many parent processes preceded them.
   Each process spawns one or multiple recursive copies of
   itself, passing 'depth+1' as depth.

   Some children are started with the '-k' flag, which will
   result in abnormal termination.
 */
int
main (int argc, char *argv[])
{
  int n;

  n = argc > 1 ? atoi (argv[1]) : 0;
  bool is_at_root = (n == 0);
  if (is_at_root)
    msg ("begin");

  /* If -k is passed, crash this process. */
  if (argc > 2 && !strcmp(argv[2], "-k"))
    {
      consume_some_resources_and_die (n);
      NOT_REACHED ();
    }

  int howmany = is_at_root ? EXPECTED_REPETITIONS : 1;
  int i, expected_depth = -1;

  for (i = 0; i < howmany; i++)
    {
      pid_t child_pid;

      /* Spawn a child that will be abnormally terminated.
         To speed the test up, do this only for processes
         spawned at a certain depth. */
      if (n > EXPECTED_DEPTH_TO_PASS/2)
        {
          child_pid = spawn_child (n + 1, CRASH);
          if (child_pid != -1)
            {
              if (wait (child_pid) != -1)
                fail ("crashed child should return -1.");
            }
          /* If spawning this child failed, so should
             the next spawn_child below. */
        }

      /* Now spawn the child that will recurse. */
      child_pid = spawn_child (n + 1, RECURSE);

      /* If maximum depth is reached, return result. */
      if (child_pid == -1)
        return n;

      /* Else wait for child to report how deeply it was able to recurse. */
      int reached_depth = wait (child_pid);
      if (reached_depth == -1)
        fail ("wait returned -1.");

      /* Record the depth reached during the first run; on subsequent
         runs, fail if those runs do not match the depth achieved on the
         first run. */
      if (i == 0)
        expected_depth = reached_depth;
      else if (expected_depth != reached_depth)
        fail ("after run %d/%d, expected depth %d, actual depth %d.",
              i, howmany, expected_depth, reached_depth);
      ASSERT (expected_depth == reached_depth);
    }

  consume_some_resources ();

  if (n == 0)
    {
      if (expected_depth < EXPECTED_DEPTH_TO_PASS)
        fail ("should have forked at least %d times.", EXPECTED_DEPTH_TO_PASS);
      msg ("success. program forked %d times.", howmany);
      msg ("end");
    }

  return expected_depth;
}
Exemple #4
0
void
memcache_parse_req(struct msg *r)
{
    struct mbuf *b;
    uint8_t *p, *m;
    uint8_t ch;
    enum {
        SW_START,
        SW_REQ_TYPE,
        SW_SPACES_BEFORE_KEY,
        SW_KEY,
        SW_SPACES_BEFORE_KEYS,
        SW_SPACES_BEFORE_FLAGS,
        SW_FLAGS,
        SW_SPACES_BEFORE_EXPIRY,
        SW_EXPIRY,
        SW_SPACES_BEFORE_VLEN,
        SW_VLEN,
        SW_SPACES_BEFORE_CAS,
        SW_CAS,
        SW_RUNTO_VAL,
        SW_VAL,
        SW_SPACES_BEFORE_NUM,
        SW_NUM,
        SW_RUNTO_CRLF,
        SW_CRLF,
        SW_NOREPLY,
        SW_AFTER_NOREPLY,
        SW_ALMOST_DONE,
        SW_SENTINEL
    } state;

    state = r->state;
    b = STAILQ_LAST(&r->mhdr, mbuf, next);

    ASSERT(r->request);
    ASSERT(r->protocol == MEMCACHE_ASCII);
    ASSERT(state >= SW_START && state < SW_SENTINEL);
    ASSERT(b != NULL);
    ASSERT(b->pos <= b->last);

    /* validate the parsing maker */
    ASSERT(r->pos != NULL);
    ASSERT(r->pos >= b->pos && r->pos <= b->last);

    for (p = r->pos; p < b->last; p++) {
        ch = *p;

        switch (state) {

        case SW_START:
            if (ch == ' ') {
                break;
            }

            if (!islower(ch)) {
                goto error;
            }

            /* req_start <- p; type_start <- p */
            r->token = p;
            state = SW_REQ_TYPE;

            break;

        case SW_REQ_TYPE:
            if (ch == ' ' || ch == CR) {
                /* type_end = p - 1 */
                m = r->token;
                r->token = NULL;
                r->type = MSG_UNKNOWN;

                switch (p - m) {

                case 3:
                    if (str4cmp(m, 'g', 'e', 't', ' ')) {
                        r->type = MSG_REQ_MC_GET;
                        break;
                    }

                    if (str4cmp(m, 's', 'e', 't', ' ')) {
                        r->type = MSG_REQ_MC_SET;
                        break;
                    }

                    if (str4cmp(m, 'a', 'd', 'd', ' ')) {
                        r->type = MSG_REQ_MC_ADD;
                        break;
                    }

                    if (str4cmp(m, 'c', 'a', 's', ' ')) {
                        r->type = MSG_REQ_MC_CAS;
                        break;
                    }

                    break;

                case 4:
                    if (str4cmp(m, 'g', 'e', 't', 's')) {
                        r->type = MSG_REQ_MC_GETS;
                        break;
                    }

                    if (str4cmp(m, 'i', 'n', 'c', 'r')) {
                        r->type = MSG_REQ_MC_INCR;
                        break;
                    }

                    if (str4cmp(m, 'd', 'e', 'c', 'r')) {
                        r->type = MSG_REQ_MC_DECR;
                        break;
                    }

                    if (str4cmp(m, 'q', 'u', 'i', 't')) {
                        r->type = MSG_REQ_MC_QUIT;
                        r->quit = 1;
                        break;
                    }

                    break;

                case 6:
                    if (str6cmp(m, 'a', 'p', 'p', 'e', 'n', 'd')) {
                        r->type = MSG_REQ_MC_APPEND;
                        break;
                    }

                    if (str6cmp(m, 'd', 'e', 'l', 'e', 't', 'e')) {
                        r->type = MSG_REQ_MC_DELETE;
                        break;
                    }

                    break;

                case 7:
                    if (str7cmp(m, 'p', 'r', 'e', 'p', 'e', 'n', 'd')) {
                        r->type = MSG_REQ_MC_PREPEND;
                        break;
                    }

                    if (str7cmp(m, 'r', 'e', 'p', 'l', 'a', 'c', 'e')) {
                        r->type = MSG_REQ_MC_REPLACE;
                        break;
                    }

                    break;
                }

                switch (r->type) {
                case MSG_REQ_MC_GET:
                case MSG_REQ_MC_GETS:
                case MSG_REQ_MC_DELETE:
                case MSG_REQ_MC_CAS:
                case MSG_REQ_MC_SET:
                case MSG_REQ_MC_ADD:
                case MSG_REQ_MC_REPLACE:
                case MSG_REQ_MC_APPEND:
                case MSG_REQ_MC_PREPEND:
                case MSG_REQ_MC_INCR:
                case MSG_REQ_MC_DECR:
                    if (ch == CR) {
                        goto error;
                    }
                    state = SW_SPACES_BEFORE_KEY;
                    break;

                case MSG_REQ_MC_QUIT:
                    p = p - 1; /* go back by 1 byte */
                    state = SW_CRLF;
                    break;

                case MSG_UNKNOWN:
                    goto error;

                default:
                    NOT_REACHED();
                }

            } else if (!islower(ch)) {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_KEY:
            if (ch != ' ') {
                r->token = p;
                r->key_start = p;
                state = SW_KEY;
            }

            break;

        case SW_KEY:
            if (ch == ' ' || ch == CR) {
                if ((p - r->key_start) > MEMCACHE_MAX_KEY_LENGTH) {
                    log_error("parsed bad req %"PRIu64" of type %d with key "
                              "prefix '%.*s...' and length %d that exceeds "
                              "maximum key length", r->id, r->type, 16,
                              r->key_start, p - r->key_start);
                    goto error;
                }
                r->key_end = p;
                r->token = NULL;

                /* get next state */
                if (memcache_storage(r)) {
                    state = SW_SPACES_BEFORE_FLAGS;
                } else if (memcache_arithmetic(r)) {
                    state = SW_SPACES_BEFORE_NUM;
                } else if (memcache_delete(r)) {
                    state = SW_RUNTO_CRLF;
                } else if (memcache_retrieval(r)) {
                    state = SW_SPACES_BEFORE_KEYS;
                } else {
                    state = SW_RUNTO_CRLF;
                }

                if (ch == CR) {
                    if (memcache_storage(r) || memcache_arithmetic(r)) {
                        goto error;
                    }
                    p = p - 1; /* go back by 1 byte */
                }
            }

            break;

        case SW_SPACES_BEFORE_KEYS:
            ASSERT(memcache_retrieval(r));
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                r->token = p;
                goto fragment;
            }

            break;

        case SW_SPACES_BEFORE_FLAGS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* flags_start <- p; flags <- ch - '0' */
                r->token = p;
                state = SW_FLAGS;
            }

            break;

        case SW_FLAGS:
            if (isdigit(ch)) {
                /* flags <- flags * 10 + (ch - '0') */
                ;
            } else if (ch == ' ') {
                /* flags_end <- p - 1 */
                r->token = NULL;
                state = SW_SPACES_BEFORE_EXPIRY;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_EXPIRY:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* expiry_start <- p; expiry <- ch - '0' */
                r->token = p;
                state = SW_EXPIRY;
            }

            break;

        case SW_EXPIRY:
            if (isdigit(ch)) {
                /* expiry <- expiry * 10 + (ch - '0') */
                ;
            } else if (ch == ' ') {
                /* expiry_end <- p - 1 */
                r->token = NULL;
                state = SW_SPACES_BEFORE_VLEN;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_VLEN:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* vlen_start <- p */
                r->token = p;
                r->vlen = (uint32_t)(ch - '0');
                state = SW_VLEN;
            }

            break;

        case SW_VLEN:
            if (isdigit(ch)) {
                r->vlen = r->vlen * 10 + (uint32_t)(ch - '0');
            } else if (memcache_cas(r)) {
                if (ch != ' ') {
                    goto error;
                }
                /* vlen_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_SPACES_BEFORE_CAS;
            } else if (ch == ' ' || ch == CR) {
                /* vlen_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_CAS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* cas_start <- p; cas <- ch - '0' */
                r->token = p;
                state = SW_CAS;
            }

            break;

        case SW_CAS:
            if (isdigit(ch)) {
                /* cas <- cas * 10 + (ch - '0') */
                ;
            } else if (ch == ' ' || ch == CR) {
                /* cas_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;


        case SW_RUNTO_VAL:
            switch (ch) {
            case LF:
                /* val_start <- p + 1 */
                state = SW_VAL;
                break;

            default:
                goto error;
            }

            break;

        case SW_VAL:
            m = p + r->vlen;
            if (m >= b->last) {
                ASSERT(r->vlen >= (uint32_t)(b->last - p));
                r->vlen -= (uint32_t)(b->last - p);
                m = b->last - 1;
                p = m; /* move forward by vlen bytes */
                break;
            }
            switch (*m) {
            case CR:
                /* val_end <- p - 1 */
                p = m; /* move forward by vlen bytes */
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_NUM:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* num_start <- p; num <- ch - '0'  */
                r->token = p;
                state = SW_NUM;
            }

            break;

        case SW_NUM:
            if (isdigit(ch)) {
                /* num <- num * 10 + (ch - '0') */
                ;
            } else if (ch == ' ' || ch == CR) {
                r->token = NULL;
                /* num_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RUNTO_CRLF:
            switch (ch) {
            case ' ':
                break;

            case 'n':
                if (memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r)) {
                    /* noreply_start <- p */
                    r->token = p;
                    state = SW_NOREPLY;
                } else {
                    goto error;
                }

                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }

                break;

            default:
                goto error;
            }

            break;

        case SW_NOREPLY:
            switch (ch) {
            case ' ':
            case CR:
                m = r->token;
                if (((p - m) == 7) && str7cmp(m, 'n', 'o', 'r', 'e', 'p', 'l', 'y')) {
                    ASSERT(memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r));
                    r->token = NULL;
                    /* noreply_end <- p - 1 */
                    r->noreply = 1;
                    state = SW_AFTER_NOREPLY;
                    p = p - 1; /* go back by 1 byte */
                } else {
                    goto error;
                }
            }

            break;

        case SW_AFTER_NOREPLY:
            switch (ch) {
            case ' ':
                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }
                break;

            default:
                goto error;
            }

            break;

        case SW_CRLF:
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_ALMOST_DONE:
            switch (ch) {
            case LF:
                /* req_end <- p */
                goto done;

            default:
                goto error;
            }

            break;

        case SW_SENTINEL:
        default:
            NOT_REACHED();
            break;

        }
    }

    /*
     * At this point, buffer from b->pos to b->last has been parsed completely
     * but we haven't been able to reach to any conclusion. Normally, this
     * means that we have to parse again starting from the state we are in
     * after more data has been read. The newly read data is either read into
     * a new mbuf, if existing mbuf is full (b->last == b->end) or into the
     * existing mbuf.
     *
     * The only exception to this is when the existing mbuf is full (b->last
     * is at b->end) and token marker is set, which means that we have to
     * copy the partial token into a new mbuf and parse again with more data
     * read into new mbuf.
     */
    ASSERT(p == b->last);
    r->pos = p;
    r->state = state;

    if (b->last == b->end && r->token != NULL) {
        r->pos = r->token;
        r->token = NULL;
        r->result = MSG_PARSE_REPAIR;
    } else {
        r->result = MSG_PARSE_AGAIN;
    }

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

fragment:
    ASSERT(p != b->last);
    ASSERT(r->token != NULL);
    r->pos = r->token;
    r->token = NULL;
    r->state = state;
    r->result = MSG_PARSE_FRAGMENT;

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

done:
    ASSERT(r->type > MSG_UNKNOWN && r->type < MSG_SENTINEL);
    r->pos = p + 1;
    ASSERT(r->pos <= b->last);
    r->state = SW_START;
    r->result = MSG_PARSE_OK;

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

error:
    r->result = MSG_PARSE_ERROR;
    r->state = state;
    errno = EINVAL;

    log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "parsed bad req %"PRIu64" "
                "res %d type %d state %d", r->id, r->result, r->type,
                r->state);
}
Exemple #5
0
static void
call_make_storage_req(struct context *ctx, struct call *call, uint32_t key_id,
                      long int key_vlen)
{
    struct opt *opt = &ctx->opt;
    int len;
    uint32_t i;

    for (i = 0; i < REQ_IOV_LEN; i++) {
        struct iovec *iov = &call->req.iov[i];

        switch (i) {
        case REQ_IOV_METHOD:
            iov->iov_base = req_strings[opt->method].data;
            iov->iov_len = req_strings[opt->method].len;
            break;

        case REQ_IOV_KEY:
            len = mcp_scnprintf(call->req.keyname, sizeof(call->req.keyname),
                                "%.*s%08"PRIx32" ", opt->prefix.len,
                                opt->prefix.data, key_id);
            iov->iov_base = call->req.keyname;
            iov->iov_len = (size_t)len;
            break;

        case REQ_IOV_FLAG:
            iov->iov_base = msg_strings[MSG_ZERO].data;
            iov->iov_len  = msg_strings[MSG_ZERO].len;
            break;

        case REQ_IOV_EXPIRY:
            len = mcp_scnprintf(call->req.expiry, sizeof(call->req.expiry),
                                "%"PRIu32" ", opt->expiry);
            iov->iov_base = call->req.expiry;
            iov->iov_len = (size_t)len;
            break;

        case REQ_IOV_VLEN:
            len = mcp_scnprintf(call->req.keylen, sizeof(call->req.keylen),
                                "%ld ", key_vlen);
            iov->iov_base = call->req.keylen;
            iov->iov_len = (size_t)len;
            break;

        case REQ_IOV_CAS:
            if (opt->method == REQ_CAS) {
                iov->iov_base = "1 ";
                iov->iov_len = 2;
            } else {
                iov->iov_base = NULL;
                iov->iov_len = 0;
            }
            break;

        case REQ_IOV_NOREPLY:
            if (opt->use_noreply) {
                iov->iov_base = msg_strings[MSG_NOREPLY].data;
                iov->iov_len = msg_strings[MSG_NOREPLY].len;
                call->req.noreply = 1;
            } else {
                iov->iov_base = NULL;
                iov->iov_len = 0;
                call->req.noreply = 0;
            }
            break;

        case REQ_IOV_CRLF:
            iov->iov_base = msg_strings[MSG_CRLF].data;
            iov->iov_len = msg_strings[MSG_CRLF].len;
            break;

        case REQ_IOV_VALUE:
            ASSERT(key_vlen >= 0 && key_vlen <= sizeof(ctx->buf1m));
            iov->iov_base = ctx->buf1m;
            iov->iov_len = (size_t)key_vlen;
            break;

        case REQ_IOV_CRLF2:
            iov->iov_base = msg_strings[MSG_CRLF].data;
            iov->iov_len = msg_strings[MSG_CRLF].len;
            break;

        default:
            NOT_REACHED();
        }
        call->req.send += iov->iov_len;
    }
}
Exemple #6
0
bool VideoDriver_SDL::CreateMainSurface(uint w, uint h)
{
	SDL_Surface *newscreen, *icon;
	char caption[50];
	int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
	bool want_hwpalette;

	GetAvailableVideoMode(&w, &h);

	DEBUG(driver, 1, "SDL: using mode %ux%ux%d", w, h, bpp);

	if (bpp == 0) usererror("Can't use a blitter that blits 0 bpp for normal visuals");

	char icon_path[MAX_PATH];
	if (FioFindFullPath(icon_path, lastof(icon_path), BASESET_DIR, "openttd.32.bmp") != NULL) {
		/* Give the application an icon */
		icon = SDL_CALL SDL_LoadBMP(icon_path);
		if (icon != NULL) {
			/* Get the colourkey, which will be magenta */
			uint32 rgbmap = SDL_CALL SDL_MapRGB(icon->format, 255, 0, 255);

			SDL_CALL SDL_SetColorKey(icon, SDL_SRCCOLORKEY, rgbmap);
			SDL_CALL SDL_WM_SetIcon(icon, NULL);
			SDL_CALL SDL_FreeSurface(icon);
		}
	}

	if (_use_hwpalette == 2) {
		/* Default is to autodetect when to use SDL_HWPALETTE.
		 * In this case, SDL_HWPALETTE is only used for 8bpp
		 * blitters in fullscreen.
		 *
		 * When using an 8bpp blitter on a 8bpp system in
		 * windowed mode with SDL_HWPALETTE, OpenTTD will claim
		 * the system palette, making all other applications
		 * get the wrong colours. In this case, we're better of
		 * trying to approximate the colors we need using system
		 * colors, using a shadow surface (see below).
		 *
		 * On a 32bpp system, SDL_HWPALETTE is ignored, so it
		 * doesn't matter what we do.
		 *
		 * When using a 32bpp blitter on a 8bpp system, setting
		 * SDL_HWPALETTE messes up rendering (at least on X11),
		 * so we don't do that. In this case, SDL takes care of
		 * color approximation using its own shadow surface
		 * (which we can't force in 8bpp on 8bpp mode,
		 * unfortunately).
		 */
		want_hwpalette = bpp == 8 && _fullscreen && _support8bpp == S8BPP_HARDWARE;
	} else {
		/* User specified a value manually */
		want_hwpalette = _use_hwpalette;
	}

	if (want_hwpalette) DEBUG(driver, 1, "SDL: requesting hardware palete");

	/* Free any previously allocated shadow surface */
	if (_sdl_screen != NULL && _sdl_screen != _sdl_realscreen) SDL_CALL SDL_FreeSurface(_sdl_screen);

	if (_sdl_realscreen != NULL) {
		if (_requested_hwpalette != want_hwpalette) {
			/* SDL (at least the X11 driver), reuses the
			 * same window and palette settings when the bpp
			 * (and a few flags) are the same. Since we need
			 * to hwpalette value to change (in particular
			 * when switching between fullscreen and
			 * windowed), we restart the entire video
			 * subsystem to force creating a new window.
			 */
			DEBUG(driver, 0, "SDL: Restarting SDL video subsystem, to force hwpalette change");
			SDL_CALL SDL_QuitSubSystem(SDL_INIT_VIDEO);
			SDL_CALL SDL_InitSubSystem(SDL_INIT_VIDEO);
			ClaimMousePointer();
			SetupKeyboard();
		}
	}
	/* Remember if we wanted a hwpalette. We can't reliably query
	 * SDL for the SDL_HWPALETTE flag, since it might get set even
	 * though we didn't ask for it (when SDL creates a shadow
	 * surface, for example). */
	_requested_hwpalette = want_hwpalette;

	/* DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK */
	newscreen = SDL_CALL SDL_SetVideoMode(w, h, bpp, SDL_SWSURFACE | (want_hwpalette ? SDL_HWPALETTE : 0) | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE));
	if (newscreen == NULL) {
		DEBUG(driver, 0, "SDL: Couldn't allocate a window to draw on");
		return false;
	}
	_sdl_realscreen = newscreen;

	if (bpp == 8 && (_sdl_realscreen->flags & SDL_HWPALETTE) != SDL_HWPALETTE) {
		/* Using an 8bpp blitter, if we didn't get a hardware
		 * palette (most likely because we didn't request one,
		 * see above), we'll have to set up a shadow surface to
		 * render on.
		 *
		 * Our palette will be applied to this shadow surface,
		 * while the real screen surface will use the shared
		 * system palette (which will partly contain our colors,
		 * but most likely will not have enough free color cells
		 * for all of our colors). SDL can use these two
		 * palettes at blit time to approximate colors used in
		 * the shadow surface using system colors automatically.
		 *
		 * Note that when using an 8bpp blitter on a 32bpp
		 * system, SDL will create an internal shadow surface.
		 * This shadow surface will have SDL_HWPALLETE set, so
		 * we won't create a second shadow surface in this case.
		 */
		DEBUG(driver, 1, "SDL: using shadow surface");
		newscreen = SDL_CALL SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, 0, 0, 0, 0);
		if (newscreen == NULL) {
			DEBUG(driver, 0, "SDL: Couldn't allocate a shadow surface to draw on");
			return false;
		}
	}

	/* Delay drawing for this cycle; the next cycle will redraw the whole screen */
	_num_dirty_rects = 0;

	_screen.width = newscreen->w;
	_screen.height = newscreen->h;
	_screen.pitch = newscreen->pitch / (bpp / 8);
	_screen.dst_ptr = newscreen->pixels;
	_sdl_screen = newscreen;

	/* When in full screen, we will always have the mouse cursor
	 * within the window, even though SDL does not give us the
	 * appropriate event to know this. */
	if (_fullscreen) _cursor.in_window = true;

	Blitter *blitter = BlitterFactory::GetCurrentBlitter();
	blitter->PostResize();

	InitPalette();
	switch (blitter->UsePaletteAnimation()) {
		case Blitter::PALETTE_ANIMATION_NONE:
		case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
			UpdatePalette();
			break;

		case Blitter::PALETTE_ANIMATION_BLITTER:
			if (VideoDriver::GetInstance() != NULL) blitter->PaletteAnimate(_local_palette);
			break;

		default:
			NOT_REACHED();
	}

	seprintf(caption, lastof(caption), "OpenTTD %s", _openttd_revision);
	SDL_CALL SDL_WM_SetCaption(caption, caption);

	GameSizeChanged();

	return true;
}
static void
rsp_forward_stats(struct context *ctx, struct msg *msg, struct conn *s_conn,
                  struct conn *c_conn)
{
    struct msg *pmsg;
    struct server *server;

    ASSERT(!s_conn->client && !s_conn->proxy);
    ASSERT(c_conn->client && !c_conn->proxy);
    ASSERT(!msg->request && msg->peer != NULL);

    server = s_conn->owner;
    pmsg = msg->peer;

    stats_server_incr(ctx, server, responses);
    stats_server_incr_by(ctx, server, response_bytes, msg->mlen);

    switch (msg->type) {
    case MSG_RSP_NUM:
        stats_server_incr(ctx, server, num);
        break;

    case MSG_RSP_STORED:
        stats_server_incr(ctx, server, stored);
        break;

    case MSG_RSP_NOT_STORED:
        stats_server_incr(ctx, server, not_stored);
        break;

    case MSG_RSP_EXISTS:
        stats_server_incr(ctx, server, exists);
        break;

    case MSG_RSP_NOT_FOUND:
        stats_server_incr(ctx, server, not_found);
        break;

    case MSG_RSP_END:
        stats_server_incr(ctx, server, end);
        break;

    case MSG_RSP_VALUE:
        stats_server_incr(ctx, server, value);
        break;

    case MSG_RSP_DELETED:
        stats_server_incr(ctx, server, deleted);
        break;

    case MSG_RSP_ERROR:
        log_debug(LOG_INFO, "rsp error type %d from s %d for req %"PRIu64" "
                  "type %d from c %d", msg->type, s_conn->sd, pmsg->id,
                  pmsg->type, c_conn->sd);
        stats_server_incr(ctx, server, error);
        break;

    case MSG_RSP_CLIENT_ERROR:
        log_debug(LOG_INFO, "rsp error type %d from s %d for req %"PRIu64" "
                  "type %d from c %d", msg->type, s_conn->sd, pmsg->id,
                  pmsg->type, c_conn->sd);
        stats_server_incr(ctx, server, client_error);
        break;

    case MSG_RSP_SERVER_ERROR:
        log_debug(LOG_INFO, "rsp error type %d from s %d for req %"PRIu64" "
                  "type %d from c %d", msg->type, s_conn->sd, pmsg->id,
                  pmsg->type, c_conn->sd);
        stats_server_incr(ctx, server, server_error);
        break;

    default:
        NOT_REACHED();
    }
}
Exemple #8
0
static void
parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                   char *arg, struct ofpbuf *ofpacts)
{
    struct ofpact_tunnel *tunnel;
    uint16_t vid;
    ovs_be32 ip;
    uint8_t pcp;
    uint8_t tos;

    switch (code) {
    case OFPUTIL_ACTION_INVALID:
        NOT_REACHED();

    case OFPUTIL_OFPAT10_OUTPUT:
    case OFPUTIL_OFPAT11_OUTPUT:
        parse_output(arg, ofpacts);
        break;

    case OFPUTIL_OFPAT10_SET_VLAN_VID:
    case OFPUTIL_OFPAT11_SET_VLAN_VID:
        vid = str_to_u32(arg);
        if (vid & ~VLAN_VID_MASK) {
            ovs_fatal(0, "%s: not a valid VLAN VID", arg);
        }
        ofpact_put_SET_VLAN_VID(ofpacts)->vlan_vid = vid;
        break;

    case OFPUTIL_OFPAT10_SET_VLAN_PCP:
    case OFPUTIL_OFPAT11_SET_VLAN_PCP:
        pcp = str_to_u32(arg);
        if (pcp & ~7) {
            ovs_fatal(0, "%s: not a valid VLAN PCP", arg);
        }
        ofpact_put_SET_VLAN_PCP(ofpacts)->vlan_pcp = pcp;
        break;

    case OFPUTIL_OFPAT12_SET_FIELD:
        set_field_parse(arg, ofpacts);
        break;

    case OFPUTIL_OFPAT10_STRIP_VLAN:
    case OFPUTIL_OFPAT11_POP_VLAN:
        ofpact_put_STRIP_VLAN(ofpacts);
        break;

    case OFPUTIL_OFPAT10_SET_DL_SRC:
    case OFPUTIL_OFPAT11_SET_DL_SRC:
        str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
        break;

    case OFPUTIL_OFPAT10_SET_DL_DST:
    case OFPUTIL_OFPAT11_SET_DL_DST:
        str_to_mac(arg, ofpact_put_SET_ETH_DST(ofpacts)->mac);
        break;

    case OFPUTIL_OFPAT10_SET_NW_SRC:
    case OFPUTIL_OFPAT11_SET_NW_SRC:
        str_to_ip(arg, &ip);
        ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4 = ip;
        break;

    case OFPUTIL_OFPAT10_SET_NW_DST:
    case OFPUTIL_OFPAT11_SET_NW_DST:
        str_to_ip(arg, &ip);
        ofpact_put_SET_IPV4_DST(ofpacts)->ipv4 = ip;
        break;

    case OFPUTIL_OFPAT10_SET_NW_TOS:
    case OFPUTIL_OFPAT11_SET_NW_TOS:
        tos = str_to_u32(arg);
        if (tos & ~IP_DSCP_MASK) {
            ovs_fatal(0, "%s: not a valid TOS", arg);
        }
        ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos;
        break;

    case OFPUTIL_OFPAT11_DEC_NW_TTL:
        NOT_REACHED();

    case OFPUTIL_OFPAT10_SET_TP_SRC:
    case OFPUTIL_OFPAT11_SET_TP_SRC:
        ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg);
        break;

    case OFPUTIL_OFPAT10_SET_TP_DST:
    case OFPUTIL_OFPAT11_SET_TP_DST:
        ofpact_put_SET_L4_DST_PORT(ofpacts)->port = str_to_u32(arg);
        break;

    case OFPUTIL_OFPAT10_ENQUEUE:
        parse_enqueue(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_RESUBMIT:
        parse_resubmit(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_SET_TUNNEL:
    case OFPUTIL_NXAST_SET_TUNNEL64:
        tunnel = ofpact_put_SET_TUNNEL(ofpacts);
        tunnel->ofpact.compat = code;
        tunnel->tun_id = str_to_u64(arg);
        break;

    case OFPUTIL_NXAST_WRITE_METADATA:
        parse_metadata(ofpacts, arg);
        break;

    case OFPUTIL_NXAST_SET_QUEUE:
        ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg);
        break;

    case OFPUTIL_NXAST_POP_QUEUE:
        ofpact_put_POP_QUEUE(ofpacts);
        break;

    case OFPUTIL_NXAST_REG_MOVE:
        nxm_parse_reg_move(ofpact_put_REG_MOVE(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_REG_LOAD:
        nxm_parse_reg_load(ofpact_put_REG_LOAD(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_NOTE:
        parse_note(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_MULTIPATH:
        multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_AUTOPATH__DEPRECATED:
        autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg);
        break;

    case OFPUTIL_NXAST_BUNDLE:
        bundle_parse(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_BUNDLE_LOAD:
        bundle_parse_load(arg, ofpacts);
        break;

    case OFPUTIL_NXAST_RESUBMIT_TABLE:
    case OFPUTIL_NXAST_OUTPUT_REG:
    case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
        NOT_REACHED();

    case OFPUTIL_NXAST_LEARN:
        learn_parse(arg, flow, ofpacts);
        break;

    case OFPUTIL_NXAST_EXIT:
        ofpact_put_EXIT(ofpacts);
        break;

    case OFPUTIL_NXAST_DEC_TTL:
        parse_dec_ttl(ofpacts, arg);
        break;

    case OFPUTIL_NXAST_FIN_TIMEOUT:
        parse_fin_timeout(ofpacts, arg);
        break;

    case OFPUTIL_NXAST_CONTROLLER:
        parse_controller(ofpacts, arg);
        break;
    }
}
Exemple #9
0
/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
 * If 'actions' is specified, an action must be in 'string' and may be expanded
 * or reallocated.
 *
 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
 * constant for 'command'.  To parse syntax for an OFPST_FLOW or
 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */
void
parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
              bool verbose)
{
    enum {
        F_OUT_PORT = 1 << 0,
        F_ACTIONS = 1 << 1,
        F_TIMEOUT = 1 << 3,
        F_PRIORITY = 1 << 4,
        F_FLAGS = 1 << 5,
    } fields;
    char *string = xstrdup(str_);
    char *save_ptr = NULL;
    char *act_str = NULL;
    char *name;

    switch (command) {
    case -1:
        fields = F_OUT_PORT;
        break;

    case OFPFC_ADD:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    case OFPFC_DELETE:
        fields = F_OUT_PORT;
        break;

    case OFPFC_DELETE_STRICT:
        fields = F_OUT_PORT | F_PRIORITY;
        break;

    case OFPFC_MODIFY:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    case OFPFC_MODIFY_STRICT:
        fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
        break;

    default:
        NOT_REACHED();
    }

    match_init_catchall(&fm->match);
    fm->priority = OFP_DEFAULT_PRIORITY;
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
        /* For modify, by default, don't update the cookie. */
        fm->new_cookie = htonll(UINT64_MAX);
    } else{
        fm->new_cookie = htonll(0);
    }
    fm->table_id = 0xff;
    fm->command = command;
    fm->idle_timeout = OFP_FLOW_PERMANENT;
    fm->hard_timeout = OFP_FLOW_PERMANENT;
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = 0;
    if (fields & F_ACTIONS) {
        act_str = strstr(string, "action");
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }
        *act_str = '\0';

        act_str = strchr(act_str + 1, '=');
        if (!act_str) {
            ofp_fatal(str_, verbose, "must specify an action");
        }

        act_str++;
    }
    for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
         name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
        const struct protocol *p;

        if (parse_protocol(name, &p)) {
            match_set_dl_type(&fm->match, htons(p->dl_type));
            if (p->nw_proto) {
                match_set_nw_proto(&fm->match, p->nw_proto);
            }
        } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
            fm->flags |= OFPFF_SEND_FLOW_REM;
        } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
            fm->flags |= OFPFF_CHECK_OVERLAP;
        } else {
            char *value;

            value = strtok_r(NULL, ", \t\r\n", &save_ptr);
            if (!value) {
                ofp_fatal(str_, verbose, "field %s missing value", name);
            }

            if (!strcmp(name, "table")) {
                fm->table_id = str_to_table_id(value);
            } else if (!strcmp(name, "out_port")) {
                if (!ofputil_port_from_string(name, &fm->out_port)) {
                    ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port",
                              name);
                }
            } else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
                fm->priority = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
                fm->idle_timeout = str_to_u16(value, name);
            } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
                fm->hard_timeout = str_to_u16(value, name);
            } else if (!strcmp(name, "cookie")) {
                char *mask = strchr(value, '/');

                if (mask) {
                    /* A mask means we're searching for a cookie. */
                    if (command == OFPFC_ADD) {
                        ofp_fatal(str_, verbose, "flow additions cannot use "
                                  "a cookie mask");
                    }
                    *mask = '\0';
                    fm->cookie = htonll(str_to_u64(value));
                    fm->cookie_mask = htonll(str_to_u64(mask+1));
                } else {
                    /* No mask means that the cookie is being set. */
                    if (command != OFPFC_ADD && command != OFPFC_MODIFY
                            && command != OFPFC_MODIFY_STRICT) {
                        ofp_fatal(str_, verbose, "cannot set cookie");
                    }
                    fm->new_cookie = htonll(str_to_u64(value));
                }
            } else if (mf_from_name(name)) {
                parse_field(mf_from_name(name), value, &fm->match);
            } else if (!strcmp(name, "duration")
                       || !strcmp(name, "n_packets")
                       || !strcmp(name, "n_bytes")) {
                /* Ignore these, so that users can feed the output of
                 * "ovs-ofctl dump-flows" back into commands that parse
                 * flows. */
            } else {
                ofp_fatal(str_, verbose, "unknown keyword %s", name);
            }
        }
    }
    if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
            && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
        /* On modifies without a mask, we are supposed to add a flow if
         * one does not exist.  If a cookie wasn't been specified, use a
         * default of zero. */
        fm->new_cookie = htonll(0);
    }
    if (fields & F_ACTIONS) {
        struct ofpbuf ofpacts;

        ofpbuf_init(&ofpacts, 32);
        str_to_inst_ofpacts(&fm->match.flow, act_str, &ofpacts);
        fm->ofpacts_len = ofpacts.size;
        fm->ofpacts = ofpbuf_steal_data(&ofpacts);
    } else {
        fm->ofpacts_len = 0;
        fm->ofpacts = NULL;
    }

    free(string);
}
Exemple #10
0
static void
syscall_handler (struct intr_frame *f)
{
/*  printf ("system call!\n");//TODO remove
  thread_exit ();*/
  uint32_t ret_val;

  offset = f->esp;
  int sys_call = (int) next_arg();

  char *tmp; //TODO remove
  


  switch (sys_call) {
  case SYS_HALT:
    power_off();
    NOT_REACHED ();

  case SYS_EXIT:
    syscall_exit((int) next_arg());
    NOT_REACHED ();

  case SYS_EXEC:
    ret_val = exec();
    break;

  case SYS_WAIT:
    ret_val = process_wait((tid_t) next_arg());
    break;

  case SYS_CREATE:
//    printf("test\n");
//    printf("file_name: %s, size: %d\n", next_str(), next_arg());
    tmp = next_str();
    ret_val = filesys_create(tmp, next_arg());
    break;

  case SYS_REMOVE:
    ret_val = filesys_remove(next_str());
    break;

  case SYS_OPEN:
    next_str();
    break;

  case SYS_FILESIZE:
    next_arg();
    break;

  case SYS_READ:
    /* next_arg(); next_arg(); next_arg(); */
	 ret_val = syscall_read();
    break;

  case SYS_WRITE:
    //FIXME this is just a temporary function to print to console unil real call is implemented
    /*if ((int) next_arg() == STDOUT_FILENO) {
      printf("%s", (char *) next_arg());
    }*/
	 ret_val = syscall_write();
    break;

  case SYS_SEEK:

    break;

  case SYS_TELL:

    break;

  case SYS_CLOSE:

    break;

  default:
    //TODO print error message
    break;
  }
  f->eax = ret_val;
}
Exemple #11
0
/**
 * Stages cargo for unloading. The cargo is sorted so that packets to be
 * transferred, delivered or kept are in consecutive chunks in the list. At the
 * same time the designation_counts are updated to reflect the size of those
 * chunks.
 * @param accepted If the cargo will be accepted at the station.
 * @param current_station ID of the station.
 * @param next_station ID of the station the vehicle will go to next.
 * @param order_flags OrderUnloadFlags that will apply to the unload operation.
 * @param ge GoodsEntry for getting the flows.
 * @param payment Payment object for registering transfers.
 * return If any cargo will be unloaded.
 */
bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment)
{
	this->AssertCountConsistency();
	assert(this->action_counts[MTA_LOAD] == 0);
	this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_DELIVER] = this->action_counts[MTA_KEEP] = 0;
	Iterator deliver = this->packets.end();
	Iterator it = this->packets.begin();
	uint sum = 0;

	bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
	bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
	bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
	assert(this->count > 0 || it == this->packets.end());
	while (sum < this->count) {
		CargoPacket *cp = *it;

		this->packets.erase(it++);
		StationID cargo_next = INVALID_STATION;
		MoveToAction action = MTA_LOAD;
		if (force_keep) {
			action = MTA_KEEP;
		} else if (force_unload && accepted && cp->source != current_station) {
			action = MTA_DELIVER;
		} else if (force_transfer) {
			action = MTA_TRANSFER;
			cargo_next = ge->GetVia(cp->source, current_station, next_station);
			assert((cargo_next != next_station || cargo_next == INVALID_STATION) &&
					cargo_next != current_station);
		} else {
			/* Rewrite an invalid source station to some random other one to
			 * avoid keeping the cargo in the vehicle forever. */
			if (cp->source == INVALID_STATION && !ge->flows.empty()) {
				cp->source = ge->flows.begin()->first;
			}
			cargo_next = ge->GetVia(cp->source);
			if (cargo_next == INVALID_STATION) {
				action = (accepted && cp->source != current_station) ? MTA_DELIVER : MTA_KEEP;
			} else if (cargo_next == current_station) {
				action = MTA_DELIVER;
			} else if (cargo_next == next_station) {
				action = MTA_KEEP;
			} else {
				action = MTA_TRANSFER;
			}
		}
		Money share;
		switch (action) {
			case MTA_KEEP:
				this->packets.push_back(cp);
				if (deliver == this->packets.end()) --deliver;
				break;
			case MTA_DELIVER:
				this->packets.insert(deliver, cp);
				break;
			case MTA_TRANSFER:
				this->packets.push_front(cp);
				/* Add feeder share here to allow reusing field for next station. */
				share = payment->PayTransfer(cp, cp->count);
				cp->AddFeederShare(share);
				this->feeder_share += share;
				cp->next_station = cargo_next;
				break;
			default:
				NOT_REACHED();
		}
		this->action_counts[action] += cp->count;
		sum += cp->count;
	}
	this->AssertCountConsistency();
	return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
}
Exemple #12
0
/**
 * Build a path from #_path_builder xpos/ypos to the mouse cursor position.
 * @param mousexy Mouse position.
 */
void PathBuildManager::ComputeNewLongPath(const Point32 &mousexy)
{
	static const TrackSlope slope_prios_down[] = {TSL_DOWN, TSL_FLAT, TSL_UP,   TSL_INVALID}; // Order of preference when going down.
	static const TrackSlope slope_prios_flat[] = {TSL_FLAT, TSL_UP,   TSL_DOWN, TSL_INVALID}; // Order of preference when at the right height.
	static const TrackSlope slope_prios_up[]   = {TSL_UP,   TSL_FLAT, TSL_DOWN, TSL_INVALID}; // Order of preference when going up.

	Viewport *vp = GetViewport();
	if (vp == nullptr) return;

	int c1, c2, c3;
	switch (vp->orientation) {
		case VOR_NORTH: c1 =  1; c2 =  2; c3 =  2; break;
		case VOR_EAST:  c1 = -1; c2 = -2; c3 =  2; break;
		case VOR_SOUTH: c1 =  1; c2 = -2; c3 = -2; break;
		case VOR_WEST:  c1 = -1; c2 =  2; c3 = -2; break;
		default: NOT_REACHED();
	}

	XYZPoint16 path_pos(0, 0, 0);
	path_pos.y = this->pos.y * 256 + 128;
	int32 lambda_y = path_pos.y - mousexy.y; // Distance to constant Y plane at current tile cursor.
	path_pos.x = this->pos.x * 256 + 128;
	int32 lambda_x = path_pos.x - mousexy.x; // Distance to constant X plane at current tile cursor.

	if (abs(lambda_x) < abs(lambda_y)) {
		/* X constant. */
		path_pos.x /= 256;
		path_pos.y = Clamp<int32>(mousexy.y + c1 * lambda_x, 0, _world.GetYSize() * 256 - 1) / 256;
		path_pos.z = Clamp<int32>(vp->view_pos.z + c3 * lambda_x, 0, WORLD_Z_SIZE * 256 - 1) / 256;
	} else {
		/* Y constant. */
		path_pos.x = Clamp<int32>(mousexy.x + c1 * lambda_y, 0, _world.GetXSize() * 256 - 1) / 256;
		path_pos.y /= 256;
		path_pos.z = Clamp<int32>(vp->view_pos.z + c2 * lambda_y, 0, WORLD_Z_SIZE * 256 - 1) / 256;
	}

	if (this->long_pos != path_pos) {
		this->long_pos = path_pos;

		_additions.Clear();
		path_pos = this->pos;
		/* Find the right direction from the selected tile to the current cursor location. */
		TileEdge direction;
		Point16 dxy;
		for (direction = EDGE_BEGIN; direction < EDGE_COUNT; direction++) {
			dxy = _tile_dxy[direction];
			if (!GoodDirection(dxy.x, path_pos.x, this->long_pos.x) || !GoodDirection(dxy.y, path_pos.y, this->long_pos.y)) continue;
			break;
		}
		if (direction == EDGE_COUNT) return;

		/* 'Walk' to the cursor as long as possible. */
		while (path_pos.x != this->long_pos.x || path_pos.y != this->long_pos.y) {
			uint8 slopes = CanBuildPathFromEdge(path_pos, direction);
			const TrackSlope *slope_prio;
			/* Get order of slope preference. */
			if (path_pos.z > this->long_pos.z) {
				slope_prio = slope_prios_down;
			} else if (path_pos.z == this->long_pos.z) {
				slope_prio = slope_prios_flat;
			} else {
				slope_prio = slope_prios_up;
			}
			/* Find best slope, and take it. */
			while (*slope_prio != TSL_INVALID && (slopes & (1 << *slope_prio)) == 0) slope_prio++;
			if (*slope_prio == TSL_INVALID) break;

			path_pos.x += dxy.x;
			path_pos.y += dxy.y;

			const Voxel *v = _world.GetVoxel(path_pos);
			if (v != nullptr && HasValidPath(v)) {
				if (!ChangePath(path_pos, this->path_type, false)) break;

				if (*slope_prio == TSL_UP) path_pos.z++;
			} else {
				if (*slope_prio == TSL_UP) {
					if (!BuildUpwardPath(path_pos, static_cast<TileEdge>((direction + 2) & 3), this->path_type, false)) break;
					path_pos.z++;
				} else if (*slope_prio == TSL_DOWN) {
					v = _world.GetVoxel(path_pos + XYZPoint16(0, 0, -1));

					if (v != nullptr && HasValidPath(v)) {
						if (!ChangePath(path_pos + XYZPoint16(0, 0, -1), this->path_type, false)) break;
					} else {
						if (!BuildDownwardPath(path_pos, static_cast<TileEdge>((direction + 2) & 3), this->path_type, false)) break;
					}
					path_pos.z--;
				} else {
					if (!BuildFlatPath(path_pos, this->path_type, false)) break;
				}
			}
		}
		vp->EnableWorldAdditions();
		vp->EnsureAdditionsAreVisible();
	}
}
Exemple #13
0
static struct ring_msg *
dmsg_parse(struct dmsg *dmsg)
{
	//rstatus_t status;
	uint8_t *p, *q, *start, *end, *pipe_p;
	uint8_t *host_id, *host_addr, *ts, *node_state;
	uint32_t k, delimlen, host_id_len, host_addr_len, ts_len, node_state_len;
	char delim[] = ",,,";
	delimlen = 3;


	/* parse "host_id1,generation_ts1,host_state1,host_broadcast_address1|host_id2,generation_ts2,host_state2,host_broadcast_address2" */
	/* host_id = dc-rack-token */
	//p = dmsg->data + dmsg->mlen - 1;
	//p = dmsg->owner->pos + dmsg->owner->mlen - 1;
	p = dmsg->payload + dmsg->plen - 1;
	end = p;

	//start = dmsg->data;
	//start = dmsg->owner->pos;
	start = dmsg->payload;

	log_debug(LOG_VERB, "parsing msg '%.*s'", dmsg->plen, start);
	host_id = NULL;
	host_addr = NULL;
	ts = NULL;
	node_state = NULL;

	host_id_len = 0;
	host_addr_len = 0;
	ts_len = 0;
	node_state_len = 0;
	pipe_p = start;
	int count = 0;

	do {
		q = dn_strrchr(p, start, '|');
		count++;
		p = q - 1;
	} while (q != NULL);

	struct ring_msg *ring_msg = create_ring_msg_with_size(count, true);
	if (ring_msg == NULL) {
		log_debug(LOG_ERR, "Error: unable to create a new ring msg!");
		//we just drop this msg
		return NULL;
	}

	struct server_pool *sp = (struct server_pool *) dmsg->owner->owner->owner;
	ring_msg->sp = sp;
	ring_msg->cb = gossip_msg_peer_update;

	count = 0;
	//p = dmsg->data + dmsg->mlen - 1;
    p = dmsg->payload + dmsg->plen - 1;

	do {

		for (k = 0; k < sizeof(delim)-1; k++) {
			q = dn_strrchr(p, start, delim[k]);

			switch (k) {
			case 0:
				host_addr = q + 1;
				host_addr_len = (uint32_t)(p - host_addr + 1);
				break;
			case 1:
				node_state = q + 1;
				node_state_len = (uint32_t)(p - node_state + 1);

				break;
			case 2:
				ts = q + 1;
				ts_len = (uint32_t)(p - ts + 1);

				break;

			default:
				NOT_REACHED();
			}
			p = q - 1;

		}

		if (k != delimlen) {
			loga("Error: this is insanely bad");
			return NULL;// DN_ERROR;
		}

		pipe_p = dn_strrchr(p, start, '|');

		if (pipe_p == NULL) {
			pipe_p = start;
		} else {
			pipe_p = pipe_p + 1;
			p = pipe_p - 2;
		}

		//host_id = dmsg->data;
		//host_id_len = dmsg->mlen - (host_addr_len + node_state_len + ts_len + 3);
		host_id = pipe_p;
		host_id_len = end - pipe_p - (host_addr_len + node_state_len + ts_len + 3) + 1;

		end = p;

#ifdef DN_DEBUG_LOG
		log_hexdump(LOG_VERB, host_id, host_id_len, "host_id: ");
		log_hexdump(LOG_VERB, ts, ts_len, "ts: ");
		log_hexdump(LOG_VERB, node_state, node_state_len, "state: ");
		log_hexdump(LOG_VERB, host_addr, host_addr_len, "host_addr: ");

		log_debug(LOG_VERB, "\t\t host_id          : '%.*s'", host_id_len, host_id);
		log_debug(LOG_VERB, "\t\t ts               : '%.*s'", ts_len, ts);
		log_debug(LOG_VERB, "\t\t node_state          : '%.*s'", node_state_len, node_state);
		log_debug(LOG_VERB, "\t\t host_addr          : '%.*s'", host_addr_len, host_addr);
#endif

		struct node *rnode = (struct node *) array_get(&ring_msg->nodes, count);
		dmsg_parse_host_id(host_id, host_id_len, &rnode->dc, &rnode->rack, &rnode->token);

#ifdef DN_DEBUG_LOG
		print_dyn_token(&rnode->token, 5);
#endif

		string_copy(&rnode->name, host_addr, host_addr_len);
		string_copy(&rnode->pname, host_addr, host_addr_len); //need to add port

		rnode->port = sp->d_port;
		rnode->is_local = false;
		rnode->is_seed = false;

		ts[ts_len] = '\0';
		rnode->ts = atol(ts);

		node_state[node_state_len] = '\0';
		rnode->state = (uint8_t) atoi(node_state);

		count++;
	} while (pipe_p != start);

	//TODOs: should move this outside
	dmsg_to_gossip(ring_msg);

	return ring_msg;
}
Exemple #14
0
static bool 
dyn_parse_core(struct msg *r)
{
	struct dmsg *dmsg;
	struct mbuf *b;
	uint8_t *p;
	uint8_t ch;
	uint64_t num = 0;

	state = r->dyn_state;
	b = STAILQ_LAST(&r->mhdr, mbuf, next);

	dmsg = r->dmsg;
	if (dmsg == NULL) {
		r->dmsg = dmsg_get();
		dmsg = r->dmsg;
		if (dmsg == NULL) {//should track this as a dropped message
			goto error; //should count as OOM error
		}
	}

	//log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "dyn parser: parsed req %"PRIu64" res %d type %d", r->id, r->result, r->type, r->dyn_state);

	for (p = r->pos; p < b->last; p++) {
		ch = *p;
		switch (state) {
		case DYN_START:
			//log_debug(LOG_DEBUG, "DYN_START");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_MAGIC_NUMBER;
			} else {
				goto skip;
			}

			break;

		case DYN_MAGIC_NUMBER:
			//log_debug(LOG_DEBUG, "DYN_MAGIC_NUMBER");
			//log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (num == MAGIC_NUMBER) {
					state = DYN_SPACES_BEFORE_MSG_ID;
				} else {
					goto error;
				}
			}

			break;

		case DYN_SPACES_BEFORE_MSG_ID:
			//log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_MSG_ID");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_MSG_ID;
			}  else {
				goto error;
			}

			break;

		case DYN_MSG_ID:
			log_debug(LOG_DEBUG, "DYN_MSG_ID");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else if (ch != ' ') {
				goto error;
			} else {

				//if (num >= 0) {
				//log_debug(LOG_DEBUG, "MSG ID : %d", num);
				dmsg->id = num;
				state = DYN_SPACES_BEFORE_TYPE_ID;
				//} else {
					//   goto error;
				//}
			}
			break;

		case DYN_SPACES_BEFORE_TYPE_ID:
			log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_TYPE_ID");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_TYPE_ID;
			}  else {
				goto error;
			}

			break;

		case DYN_TYPE_ID:
			log_debug(LOG_DEBUG, "DYN_TYPE_ID");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (num > 0)  {
					log_debug(LOG_DEBUG, "Type Id: %d", num);
					dmsg->type = num;
					//state = DYN_SPACES_BEFORE_VERSION;
					state = DYN_SPACES_BEFORE_BIT_FIELD;
				} else {
					goto error;
				}
			}

			break;

		case DYN_SPACES_BEFORE_BIT_FIELD:
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_BIT_FIELD;
			} else {
				goto error;
			}
			break;

		case DYN_BIT_FIELD:
			log_debug(LOG_DEBUG, "DYN_BIT_FIELD");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == ' ')  {
					log_debug(LOG_DEBUG, "DYN_BIT_FIELD : %d", num);
					dmsg->bit_field = num & 0xF;
					state = DYN_SPACES_BEFORE_VERSION;
				} else {
					goto error;
				}
			}

			log_debug(LOG_DEBUG, "Post DYN_BIT_FIELD");
			log_debug(LOG_DEBUG, "num = %d", num);

			break;

		case DYN_SPACES_BEFORE_VERSION:
			log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_VERSION");
			if (ch == ' ') {
				break;
			} else if (isdigit(ch)) {
				num = ch - '0';
				state = DYN_VERSION;
			}  else {
				goto error;
			}

			break;

		case DYN_VERSION:
			log_debug(LOG_DEBUG, "DYN_VERSION");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == ' ')  {
					//log_debug(LOG_DEBUG, "VERSION : %d", num);
					dmsg->version = num;
					state = DYN_SPACES_BEFORE_STAR;
				} else {
					goto error;
				}
			}

			break;

		case DYN_SPACES_BEFORE_STAR:
			//log_debug(LOG_DEBUG, "DYN_CRLF_BEFORE_STAR");
			if (ch == ' ')  {
				break;
			} else if (ch == '*') {
				state = DYN_DATA_LEN;
				num = 0;
			} else {
				goto error;
			}

			//else {
			//	state = DYN_STAR;
			//}

			break;

		//case DYN_STAR:
			//log_debug(LOG_DEBUG, "DYN_STAR");
		//	if (ch == '*') {
		//		state = DYN_DATA_LEN;
		//		num = 0;
		//	} else {
		//		goto error;
		//	}

		//	break;

		case DYN_DATA_LEN:
			log_debug(LOG_DEBUG, "DYN_DATA_LEN");
			log_debug(LOG_DEBUG, "num = %d", num);
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == ' ')  {
					log_debug(LOG_DEBUG, "Data len: %d", num);
					dmsg->mlen = num;
					state = DYN_SPACE_BEFORE_DATA;
					num = 0;
				} else {
					goto error;
				}
			}
			break;

		case DYN_SPACE_BEFORE_DATA:
			log_debug(LOG_DEBUG, "DYN_SPACE_BEFORE_DATA");
			state = DYN_DATA;
			break;

		case DYN_DATA:
			log_debug(LOG_DEBUG, "DYN_DATA");
			p -= 1;
			if (dmsg->mlen > 0)  {
				dmsg->data = p;
				p += dmsg->mlen - 1;
				state = DYN_SPACES_BEFORE_PAYLOAD_LEN;
			} else {
				goto error;
			}

			break;

		case DYN_SPACES_BEFORE_PAYLOAD_LEN: //this only need in dynomite's custome msg
			log_debug(LOG_DEBUG, "DYN_SPACES_BEFORE_PAYLOAD_LEN");
			if (ch == ' ') {
				break;
			} else if (ch == '*') {
				state = DYN_PAYLOAD_LEN;
				num = 0;
			} else {
				goto error;
			}

			break;

		case DYN_PAYLOAD_LEN:
			if (isdigit(ch))  {
				num = num*10 + (ch - '0');
			} else {
				if (ch == CR)  {
					log_debug(LOG_DEBUG, "Payload len: %d", num);
					dmsg->plen = num;
					state = DYN_CRLF_BEFORE_DONE;
					num = 0;
				} else {
					goto error;
				}
			}
			break;

		case DYN_CRLF_BEFORE_DONE:
			//log_debug(LOG_DEBUG, "DYN_CRLF_BEFORE_DONE");
			if (*p == LF) {
				state = DYN_DONE;
			} else {
				goto error;
			}

			break;

		case DYN_DONE:
			//log_debug(LOG_DEBUG, "DYN_DONE");
			r->pos = p;
			dmsg->payload = p;
			r->dyn_state = DYN_DONE;
			b->pos = p;
			goto done;
			break;

		default:
			NOT_REACHED();
			break;

		}

	}

	done:

	dmsg->owner = r;
	dmsg->source_address = r->owner->addr;
    //r->mlen = mbuf_length(b);
	//log_debug(LOG_DEBUG, "at done with p at %d", p);
	dmsg_dump(r->dmsg);
	log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "dyn: parsed req %"PRIu64" res %d "
			"type %d state %d rpos %d of %d", r->id, r->result, r->type,
			r->dyn_state, r->pos - b->pos, b->last - b->pos);


	return true;

	skip:
	//log_debug(LOG_DEBUG, "This is not a dyn message");
	dmsg->type = DMSG_UNKNOWN;
	dmsg->owner = r;
	dmsg->source_address = r->owner->addr;
	return true;

	error:
	log_debug(LOG_ERR, "at error");
	r->result = MSG_PARSE_ERROR;
	r->state = state;
	errno = EINVAL;

	log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "parsed bad req %"PRIu64" "
			"res %d type %d state %d", r->id, r->result, r->type,
			r->state);
	return false;

	return true;    //fix me
}
Exemple #15
0
/**
 * Draw the details for the given vehicle at the given position
 *
 * @param v     current vehicle
 * @param left  The left most coordinate to draw
 * @param right The right most coordinate to draw
 * @param y     The y coordinate
 * @param vscroll_pos Position of scrollbar
 * @param vscroll_cap Number of lines currently displayed
 * @param det_tab Selected details tab
 */
void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab)
{
	/* draw the first 3 details tabs */
	if (det_tab != TDW_TAB_TOTALS) {
		bool rtl = _dynlang.text_dir == TD_RTL;
		Direction dir = rtl ? DIR_E : DIR_W;
		int x = rtl ? right : left;
		int sprite_y_offset = 4 + (FONT_HEIGHT_NORMAL - 10) / 2;
		int line_height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
		for (; v != NULL && vscroll_pos > -vscroll_cap; v = v->GetNextVehicle()) {
			GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);

			/* Draw sprites */
			int dx = 0;
			int px = x;
			const Train *u = v;
			do {
				Point offset;
				int width = u->GetDisplayImageWidth(&offset);
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
					SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
					DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
				}
				px += rtl ? -width : width;
				dx += width;
				u = u->Next();
			} while (u != NULL && u->IsArticulatedPart());

			bool separate_sprite_row = (dx > TRAIN_DETAILS_MAX_INDENT);
			if (separate_sprite_row) {
				vscroll_pos--;
				dx = 0;
			}

			uint num_lines = max(1u, _cargo_summary.Length());
			for (uint i = 0; i < num_lines; i++) {
				int sprite_width = max<int>(dx, TRAIN_DETAILS_MIN_INDENT) + 3;
				int data_left  = left + (rtl ? 0 : sprite_width);
				int data_right = right - (rtl ? sprite_width : 0);
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
					int py = y - line_height * vscroll_pos;
					if (i > 0 || separate_sprite_row) {
						if (vscroll_pos != 0) GfxFillRect(left, py - WD_MATRIX_TOP - 1, right, py - WD_MATRIX_TOP, _colour_gradient[COLOUR_GREY][5]);
					}
					switch (det_tab) {
						case TDW_TAB_CARGO:
							if (i < _cargo_summary.Length()) {
								TrainDetailsCargoTab(&_cargo_summary[i], data_left, data_right, py);
							} else {
								DrawString(data_left, data_right, py, STR_QUANTITY_N_A, TC_LIGHT_BLUE);
							}
							break;

						case TDW_TAB_INFO:
							if (i == 0) TrainDetailsInfoTab(v, data_left, data_right, py);
							break;

						case TDW_TAB_CAPACITY:
							if (i < _cargo_summary.Length()) {
								TrainDetailsCapacityTab(&_cargo_summary[i], data_left, data_right, py);
							} else {
								DrawString(data_left, data_right, py, STR_VEHICLE_INFO_NO_CAPACITY);
							}
							break;

						default: NOT_REACHED();
					}
				}
				vscroll_pos--;
			}
		}
	} else {
		CargoArray act_cargo;
		CargoArray max_cargo;
		Money feeder_share = 0;

		for (const Vehicle *u = v; u != NULL; u = u->Next()) {
			act_cargo[u->cargo_type] += u->cargo.Count();
			max_cargo[u->cargo_type] += u->cargo_cap;
			feeder_share             += u->cargo.FeederShare();
		}

		/* draw total cargo tab */
		DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT);
		y += WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;

		for (CargoID i = 0; i < NUM_CARGO; i++) {
			if (max_cargo[i] > 0 && --vscroll_pos < 0 && vscroll_pos > -vscroll_cap) {
				SetDParam(0, i);            // {CARGO} #1
				SetDParam(1, act_cargo[i]); // {CARGO} #2
				SetDParam(2, i);            // {SHORTCARGO} #1
				SetDParam(3, max_cargo[i]); // {SHORTCARGO} #2
				SetDParam(4, _settings_game.vehicle.freight_trains);
				DrawString(left, right, y, FreightWagonMult(i) > 1 ? STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_MULT : STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY);
				y += WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
			}
		}
		SetDParam(0, feeder_share);
		DrawString(left, right, y, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE);
	}
}
Exemple #16
0
Bool
FileIO_AtomicUpdate(FileIODescriptor *newFD,   // IN/OUT: file IO descriptor
                    FileIODescriptor *currFD)  // IN/OUT: file IO descriptor
{
    char *currPath = NULL;
    char *newPath = NULL;
#if defined(_WIN32)
    uint32 currAccess;
    uint32 newAccess;
    FileIOResult status;
    FileIODescriptor tmpFD;
#else
    int fd;
#endif
    int savedErrno = 0;
    Bool ret = FALSE;

    ASSERT(FileIO_IsValid(newFD));
    ASSERT(FileIO_IsValid(currFD));

    if (HostType_OSIsVMK()) {
#if defined(VMX86_SERVER)
        FS_SwapFilesArgs *args = NULL;
        char *dirName = NULL;
        char *fileName = NULL;
        char *dstDirName = NULL;
        char *dstFileName = NULL;

        currPath = File_FullPath(FileIO_Filename(currFD));
        if (!currPath) {
            savedErrno = errno;
            Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__,
                FileIO_Filename(currFD));
            goto swapdone;
        }

        newPath = File_FullPath(FileIO_Filename(newFD));
        if (!newPath) {
            savedErrno = errno;
            Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__,
                FileIO_Filename(newFD));
            goto swapdone;
        }

        File_GetPathName(newPath, &dirName, &fileName);
        File_GetPathName(currPath, &dstDirName, &dstFileName);

        ASSERT(dirName && *dirName);
        ASSERT(fileName && *fileName);
        ASSERT(dstDirName && *dstDirName);
        ASSERT(dstFileName && *dstFileName);
        ASSERT(!strcmp(dirName, dstDirName));

        args = (FS_SwapFilesArgs *) Util_SafeCalloc(1, sizeof(*args));
        if (Str_Snprintf(args->srcFile, sizeof(args->srcFile), "%s",
                         fileName) < 0) {
            Log("%s: Path too long \"%s\".\n", __FUNCTION__, fileName);
            savedErrno = ENAMETOOLONG;
            goto swapdone;
        }
        if (Str_Snprintf(args->dstFilePath, sizeof(args->dstFilePath), "%s/%s",
                         dstDirName, dstFileName) < 0) {
            Log("%s: Path too long \"%s\".\n", __FUNCTION__, dstFileName);
            savedErrno = ENAMETOOLONG;
            goto swapdone;
        }

        /*
         * Issue the ioctl on the directory rather than on the file,
         * because the file could be open.
         */

        fd = Posix_Open(dirName, O_RDONLY);
        if (fd < 0) {
            Log("%s: Open failed \"%s\" %d.\n", __FUNCTION__, dirName, errno);
            ASSERT(errno != EBUSY);   /* #615124. */
            savedErrno = errno;
            goto swapdone;
        }

        if (ioctl(fd, IOCTLCMD_VMFS_SWAP_FILES, args) != 0) {
            savedErrno = errno;
            if (errno != ENOSYS && errno != ENOTTY) {
                Log("%s: ioctl failed %d.\n", __FUNCTION__, errno);
                ASSERT(errno != EBUSY);   /* #615124. */
            }
        } else {
            ret = TRUE;
        }

        close(fd);

        /*
         * Did we fail because we are on a file system that does not
         * support the IOCTLCMD_VMFS_SWAP_FILES ioctl? If so fallback to
         * using rename.
         *
         * Check for both ENOSYS and ENOTTY. PR 957695
         */
        if (savedErrno == ENOSYS || savedErrno == ENOTTY) {
            /*
             * NFS allows renames of locked files, even if both files
             * are locked.  The file lock follows the file handle, not
             * the name, so after the rename we can swap the underlying
             * file descriptors instead of closing and reopening the
             * target file.
             *
             * This is different than the hosted path below because
             * ESX uses native file locks and hosted does not.
             *
             * We assume that all ESX file systems that support rename
             * have the same file lock semantics as NFS.
             */

            if (File_Rename(newPath, currPath)) {
                Log("%s: rename of '%s' to '%s' failed %d.\n",
                    __FUNCTION__, newPath, currPath, errno);
                savedErrno = errno;
                goto swapdone;
            }
            ret = TRUE;
            fd = newFD->posix;
            newFD->posix = currFD->posix;
            currFD->posix = fd;
            FileIO_Close(newFD);
        }

swapdone:
        free(args);
        free(dirName);
        free(fileName);
        free(dstDirName);
        free(dstFileName);
        free(currPath);
        free(newPath);

        errno = savedErrno;
        return ret;
#else
        NOT_REACHED();
#endif
    }
#if defined(_WIN32)
    currPath = Unicode_Duplicate(FileIO_Filename(currFD));
    newPath = Unicode_Duplicate(FileIO_Filename(newFD));

    newAccess = newFD->flags;
    currAccess = currFD->flags;

    FileIO_Close(newFD);

    /*
     * The current file needs to be closed and reopened,
     * but we don't want to drop the file lock by calling
     * FileIO_Close() on it.  Instead, use native close primitives.
     * We'll reopen it later with FileIO_Open.  Set the
     * descriptor/handle to an invalid value while we're in the
     * middle of transferring ownership.
     */

    CloseHandle(currFD->win32);
    currFD->win32 = INVALID_HANDLE_VALUE;
    if (File_RenameRetry(newPath, currPath, 10) == 0) {
        ret = TRUE;
    } else {
        savedErrno = errno;
        ASSERT(!ret);
    }

    FileIO_Invalidate(&tmpFD);

    /*
     * Clear the locking bits from the requested access so that reopening
     * the file ignores the advisory lock.
     */

    ASSERT((currAccess & FILEIO_OPEN_LOCK_MANDATORY) == 0);
    currAccess &= ~(FILEIO_OPEN_LOCK_MANDATORY | FILEIO_OPEN_LOCK_ADVISORY |
                    FILEIO_OPEN_LOCK_BEST | FILEIO_OPEN_LOCKED);
    status = FileIO_Open(&tmpFD, currPath, currAccess, FILEIO_OPEN);
    if (!FileIO_IsSuccess(status)) {
        Panic("Failed to reopen dictionary after renaming "
              "\"%s\" to \"%s\": %s (%d)\n", newPath, currPath,
              FileIO_ErrorEnglish(status), status);
    }
    ASSERT(tmpFD.lockToken == NULL);

    currFD->win32 = tmpFD.win32;

    FileIO_Cleanup(&tmpFD);
    Unicode_Free(currPath);
    Unicode_Free(newPath);
    errno = savedErrno;

    return ret;
#else
    currPath = (char *)FileIO_Filename(currFD);
    newPath = (char *)FileIO_Filename(newFD);

    if (File_Rename(newPath, currPath)) {
        Log("%s: rename of '%s' to '%s' failed %d.\n",
            __FUNCTION__, newPath, currPath, errno);
        savedErrno = errno;
    } else {
        ret = TRUE;
        fd = newFD->posix;
        newFD->posix = currFD->posix;
        currFD->posix = fd;
        FileIO_Close(newFD);
    }

    errno = savedErrno;

    return ret;
#endif
}
Exemple #17
0
int
event_wait(struct event_base *evb, int timeout)
{
    int ep = evb->ep;
    struct epoll_event *event = evb->event;
    int nevent = evb->nevent;

    ASSERT(ep > 0);
    ASSERT(event != NULL);
    ASSERT(nevent > 0);

    for (;;) {
        int i, nsd;

        nsd = epoll_wait(ep, event, nevent, timeout);
        if (nsd > 0) {
            for (i = 0; i < nsd; i++) {
                struct epoll_event *ev = &evb->event[i];
                uint32_t events = 0;

                log_debug(LOG_VVERB, "epoll %04"PRIX32" triggered on conn %p",
                          ev->events, ev->data.ptr);

                if (ev->events & EPOLLERR) {
                    events |= EVENT_ERR;
                }

                if (ev->events & (EPOLLIN | EPOLLHUP)) {
                    events |= EVENT_READ;
                }

                if (ev->events & EPOLLOUT) {
                    events |= EVENT_WRITE;
                }

                if (evb->cb != NULL) {
                    evb->cb(ev->data.ptr, events);
                }
            }
            return nsd;
        }

        if (nsd == 0) {
            if (timeout == -1) {
               log_error("epoll wait on e %d with %d events and %d timeout "
                         "returned no events", ep, nevent, timeout);
                return -1;
            }

            return 0;
        }

        if (errno == EINTR) {
            continue;
        }

        log_error("epoll wait on e %d with %d events failed: %s", ep, nevent,
                  strerror(errno));
        return -1;
    }

    NOT_REACHED();
}
Exemple #18
0
bool
operands_equal(operand_t const *op1, operand_t const *op2)
{
    if (op1->type != op2->type) {
        return false;
    }
    if (op1->size != op2->size) {
        return false;
    }
    if (op1->type == invalid) {
        return true;
    }

    switch (op1->type) {
    case op_reg:
        return (   op1->val.reg == op2->val.reg
                   && op1->tag.reg == op2->tag.reg);
    case op_seg:
        return (   op1->val.seg == op2->val.seg
                   && op1->tag.seg == op2->tag.seg);
    case op_mem:
        return (   op1->val.mem.segtype == op2->val.mem.segtype
                   && op1->val.mem.seg.all == op2->val.mem.seg.all
                   && op1->val.mem.base == op2->val.mem.base
                   && op1->val.mem.scale == op2->val.mem.scale
                   && op1->val.mem.index == op2->val.mem.index
                   && op1->val.mem.disp == op2->val.mem.disp
                   && op1->tag.mem.seg.all == op2->tag.mem.seg.all
                   && op1->tag.mem.all == op2->tag.mem.all
                   && op1->tag.mem.base == op2->tag.mem.base
                   && op1->tag.mem.index == op2->tag.mem.index
                   && op1->tag.mem.disp == op2->tag.mem.disp);
    case op_imm:   /* All tag_const imm operands should have 0 size. */
        ASSERT(op1->tag.imm != tag_const || op1->size == 0);
        ASSERT(op2->tag.imm != tag_const || op2->size == 0);
        return (   op1->val.imm == op2->val.imm
                   && op1->tag.imm == op2->tag.imm);
    case op_pcrel: /* All tag_const pcrel operands should have 0 size. */
        ASSERT(0);
        ASSERT(op1->tag.pcrel != tag_const || op1->size == 0);
        ASSERT(op2->tag.pcrel != tag_const || op2->size == 0);
        return (   op1->val.pcrel == op2->val.pcrel
                   && op1->tag.pcrel == op2->tag.pcrel);
    case op_cr:
        return (   op1->val.cr == op2->val.cr
                   && op1->tag.cr == op2->tag.cr);
    case op_db:
        return (   op1->val.db == op2->val.db
                   && op1->tag.db == op2->tag.db);
    case op_tr:
        return (   op1->val.tr == op2->val.tr
                   && op1->tag.tr == op2->tag.tr);
    case op_mmx:
        return (   op1->val.mmx == op2->val.mmx
                   && op1->tag.mmx == op2->tag.mmx);
    case op_xmm:
        return (   op1->val.xmm == op2->val.xmm
                   && op1->tag.xmm == op2->tag.xmm);
    case op_3dnow:
        return (   op1->val.d3now == op2->val.d3now
                   && op1->tag.d3now == op2->tag.d3now);
    case op_prefix:
        return (   op1->val.prefix == op2->val.prefix
                   && op1->tag.prefix == op2->tag.prefix);
    case op_st:
    case invalid:
        NOT_REACHED();
    }
    ASSERT(0);
    return false;
}
Exemple #19
0
static int
ssl_connect(struct stream *stream)
{
    struct ssl_stream *sslv = ssl_stream_cast(stream);
    int retval;

    switch (sslv->state) {
    case STATE_TCP_CONNECTING:
        retval = check_connection_completion(sslv->fd);
        if (retval) {
            return retval;
        }
        sslv->state = STATE_SSL_CONNECTING;
        /* Fall through. */

    case STATE_SSL_CONNECTING:
        /* Capture the first few bytes of received data so that we can guess
         * what kind of funny data we've been sent if SSL negotation fails. */
        if (sslv->n_head <= 0) {
            sslv->n_head = recv(sslv->fd, sslv->head, sizeof sslv->head,
                                MSG_PEEK);
        }

        retval = (sslv->type == CLIENT
                   ? SSL_connect(sslv->ssl) : SSL_accept(sslv->ssl));
        if (retval != 1) {
            int error = SSL_get_error(sslv->ssl, retval);
            if (retval < 0 && ssl_wants_io(error)) {
                return EAGAIN;
            } else {
                int unused;

                interpret_ssl_error((sslv->type == CLIENT ? "SSL_connect"
                                     : "SSL_accept"), retval, error, &unused);
                shutdown(sslv->fd, SHUT_RDWR);
                stream_report_content(sslv->head, sslv->n_head, STREAM_SSL,
                                      THIS_MODULE, stream_get_name(stream));
                return EPROTO;
            }
        } else if (bootstrap_ca_cert) {
            return do_ca_cert_bootstrap(stream);
        } else if (verify_peer_cert
                   && ((SSL_get_verify_mode(sslv->ssl)
                       & (SSL_VERIFY_NONE | SSL_VERIFY_PEER))
                       != SSL_VERIFY_PEER)) {
            /* Two or more SSL connections completed at the same time while we
             * were in bootstrap mode.  Only one of these can finish the
             * bootstrap successfully.  The other one(s) must be rejected
             * because they were not verified against the bootstrapped CA
             * certificate.  (Alternatively we could verify them against the CA
             * certificate, but that's more trouble than it's worth.  These
             * connections will succeed the next time they retry, assuming that
             * they have a certificate against the correct CA.) */
            VLOG_INFO("rejecting SSL connection during bootstrap race window");
            return EPROTO;
        } else {
            return 0;
        }
    }

    NOT_REACHED();
}
/**
 * Add the remaining articulated parts to the given vehicle.
 * @param first The head of the articulated bit.
 */
void AddArticulatedParts(Vehicle *first)
{
	VehicleType type = first->type;
	if (!HasBit(EngInfo(first->engine_type)->callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return;

	Vehicle *v = first;
	for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
		bool flip_image;
		EngineID engine_type = GetNextArticulatedPart(i, first->engine_type, first, &flip_image);
		if (engine_type == INVALID_ENGINE) return;

		/* In the (very rare) case the GRF reported wrong number of articulated parts
		 * and we run out of available vehicles, bail out. */
		if (!Vehicle::CanAllocateItem()) return;

		GroundVehicleCache *gcache = v->GetGroundVehicleCache();
		gcache->first_engine = v->engine_type; // Needs to be set before first callback

		const Engine *e_artic = Engine::Get(engine_type);
		switch (type) {
			default: NOT_REACHED();

			case VEH_TRAIN: {
				Train *front = Train::From(first);
				Train *t = new Train();
				v->SetNext(t);
				v = t;

				t->subtype = 0;
				t->track = front->track;
				t->railtype = front->railtype;

				t->spritenum = e_artic->u.rail.image_index;
				if (e_artic->CanCarryCargo()) {
					t->cargo_type = e_artic->GetDefaultCargoType();
					t->cargo_cap = e_artic->u.rail.capacity;  // Callback 36 is called when the consist is finished
				} else {
					t->cargo_type = front->cargo_type; // Needed for livery selection
					t->cargo_cap = 0;
				}

				t->SetArticulatedPart();
				break;
			}

			case VEH_ROAD: {
				RoadVehicle *front = RoadVehicle::From(first);
				RoadVehicle *rv = new RoadVehicle();
				v->SetNext(rv);
				v = rv;

				rv->subtype = 0;
				gcache->cached_veh_length = VEHICLE_LENGTH; // Callback is called when the consist is finished
				rv->state = RVSB_IN_DEPOT;

				rv->roadtype = front->roadtype;
				rv->compatible_roadtypes = front->compatible_roadtypes;

				rv->spritenum = e_artic->u.road.image_index;
				if (e_artic->CanCarryCargo()) {
					rv->cargo_type = e_artic->GetDefaultCargoType();
					rv->cargo_cap = e_artic->u.road.capacity;  // Callback 36 is called when the consist is finished
				} else {
					rv->cargo_type = front->cargo_type; // Needed for livery selection
					rv->cargo_cap = 0;
				}

				rv->SetArticulatedPart();
				break;
			}
		}

		/* get common values from first engine */
		v->direction = first->direction;
		v->owner = first->owner;
		v->tile = first->tile;
		v->x_pos = first->x_pos;
		v->y_pos = first->y_pos;
		v->z_pos = first->z_pos;
		v->build_year = first->build_year;
		v->vehstatus = first->vehstatus & ~VS_STOPPED;

		v->cargo_subtype = 0;
		v->max_age = 0;
		v->engine_type = engine_type;
		v->value = 0;
		v->cur_image = SPR_IMG_QUERY;
		v->random_bits = VehicleRandomBits();

		if (flip_image) v->spritenum++;

		VehicleMove(v, false);
	}
}
Exemple #21
0
struct conn *
conn_get(void *owner, bool client, unsigned source_type, struct conn_base *cb)
{
    struct conn *conn;

    conn = _conn_get(cb);
    if (conn == NULL) {
        return NULL;
    }

    /* this connection either handles redis or memcache messages */
    if (source_type == NC_SOURCE_TYPE_REDIS) {
        conn->source_type = NC_SOURCE_TYPE_REDIS;
    } else if (source_type == NC_SOURCE_TYPE_PROXY) {
        conn->source_type = NC_SOURCE_TYPE_PROXY;
    } else if (source_type == NC_SOURCE_TYPE_MC) {
        conn->source_type = NC_SOURCE_TYPE_MC;
    } else {
        NOT_REACHED();
    }

    conn->client = client ? 1 : 0;

    if (conn->client) {
        /*
         * client receives a request, possibly parsing it, and sends a
         * response downstream.
         */
        conn->recv = msg_recv;
        conn->recv_next = req_recv_next;
        conn->recv_done = req_recv_done;

        conn->send = msg_send;
        conn->send_next = rsp_send_next;
        conn->send_done = rsp_send_done;

        conn->close = client_close;
        conn->active = client_active;

        conn->ref = client_ref;
        conn->unref = client_unref;

        conn->enqueue_inq = NULL;
        conn->dequeue_inq = NULL;
        conn->enqueue_outq = req_client_enqueue_omsgq;
        conn->dequeue_outq = req_client_dequeue_omsgq;
        conn->post_connect = NULL;
        conn->swallow_msg = NULL;

        if (cb) cb->ncurr_cconn++;

        STATS_LOCK();
        ncurr_cconn ++;
        STATS_UNLOCK();
    } else {
        /*
         * server receives a response, possibly parsing it, and sends a
         * request upstream.
         */
        conn->recv = msg_recv;
        conn->recv_next = rsp_recv_next;
        conn->recv_done = rsp_recv_done;

        conn->send = msg_send;
        conn->send_next = req_send_next;
        conn->send_done = req_send_done;

        conn->close = server_close;
        conn->active = server_active;

        conn->ref = server_ref;
        conn->unref = server_unref;

        conn->enqueue_inq = req_server_enqueue_imsgq;
        conn->dequeue_inq = req_server_dequeue_imsgq;
        conn->enqueue_outq = req_server_enqueue_omsgq;
        conn->dequeue_outq = req_server_dequeue_omsgq;
        if (source_type == NC_SOURCE_TYPE_REDIS) {
            conn->post_connect = redis_post_connect;
            conn->swallow_msg = redis_swallow_msg;
        } else {
            conn->post_connect = memcache_post_connect;
            conn->swallow_msg = memcache_swallow_msg;
        }
    }

    if (source_type == NC_SOURCE_TYPE_PROXY) {

    }
    conn->ref(conn, owner);
    log_debug(LOG_VVERB, "get conn %p client %d", conn, conn->client);

    return conn;
}
Exemple #22
0
/* Reads a record from a disk file into R.
   Returns true if successful, false on error or at end of file. */
static bool
read_file_record (struct dfm_reader *r)
{
  assert (r->fh != fh_inline_file ());

  ds_clear (&r->line);
  switch (fh_get_mode (r->fh))
    {
    case FH_MODE_TEXT:
      if (ds_read_line (&r->line, r->file, SIZE_MAX))
        {
          ds_chomp_byte (&r->line, '\n');
          return true;
        }
      else
        {
          if (ferror (r->file))
            read_error (r);
          return false;
        }

    case FH_MODE_FIXED:
      if (ds_read_stream (&r->line, 1, fh_get_record_width (r->fh), r->file))
        return true;
      else
        {
          if (ferror (r->file))
            read_error (r);
          else if (!ds_is_empty (&r->line))
            partial_record (r);
          return false;
        }

    case FH_MODE_VARIABLE:
      {
        size_t leading_size;
        size_t trailing_size;
        int status;

        /* Read leading record size. */
        status = read_size (r, &leading_size);
        if (status <= 0)
          return false;

        /* Read record data. */
        if (!ds_read_stream (&r->line, leading_size, 1, r->file))
          {
            if (ferror (r->file))
              read_error (r);
            else
              partial_record (r);
            return false;
          }

        /* Read trailing record size and check that it's the same
           as the leading record size. */
        status = read_size (r, &trailing_size);
        if (status <= 0)
          {
            if (status == 0)
              partial_record (r);
            return false;
          }
        if (leading_size != trailing_size)
          {
            corrupt_size (r);
            return false;
          }

        return true;
      }

    case FH_MODE_360_VARIABLE:
    case FH_MODE_360_SPANNED:
      for (;;)
        {
          size_t record_size;
          int segment;
          int status;

          /* If we've exhausted our current block, start another
             one by reading the new block descriptor word. */
          if (r->block_left == 0)
            {
              status = read_descriptor_word (r, BLOCK, &r->block_left, NULL);
              if (status < 0)
                return false;
              else if (status == 0)
                return !ds_is_empty (&r->line);
            }

          /* Read record descriptor. */
          if (r->block_left < 4)
            {
              partial_record (r);
              return false;
            }
          r->block_left -= 4;
          status = read_descriptor_word (r, RECORD, &record_size, &segment);
          if (status <= 0)
            {
              if (status == 0)
                partial_record (r);
              return false;
            }
          if (record_size > r->block_left)
            {
              msg (ME, _("Record exceeds remaining block length."));
              return false;
            }

          /* Read record data. */
          if (!ds_read_stream (&r->line, record_size, 1, r->file))
            {
              if (ferror (r->file))
                read_error (r);
              else
                partial_record (r);
              return false;
            }
          r->block_left -= record_size;

          /* In variable mode, read only a single record.
             In spanned mode, a segment value of 0 should
             designate a whole record without spanning, 1 the
             first segment in a record, 2 the last segment in a
             record, and 3 an intermediate segment in a record.
             For compatibility, though, we actually pay attention
             only to whether the segment value is even or odd. */
          if (fh_get_mode (r->fh) == FH_MODE_360_VARIABLE
              || (segment & 1) == 0)
            return true;
        }
    }

  NOT_REACHED ();
}
Exemple #23
0
void
memcache_parse_rsp(struct msg *r)
{
    struct mbuf *b;
    uint8_t *p, *m;
    uint8_t ch;
    enum {
        SW_START,
        SW_RSP_NUM,
        SW_RSP_STR,
        SW_SPACES_BEFORE_KEY,
        SW_KEY,
        SW_SPACES_BEFORE_FLAGS,
        SW_FLAGS,
        SW_SPACES_BEFORE_VLEN,
        SW_VLEN,
        SW_RUNTO_VAL,
        SW_VAL,
        SW_VAL_LF,
        SW_END,
        SW_RUNTO_CRLF,
        SW_CRLF,
        SW_ALMOST_DONE,
        SW_SENTINEL
    } state;

    state = r->state;
    b = STAILQ_LAST(&r->mhdr, mbuf, next);

    ASSERT(!r->request);
    ASSERT(r->protocol == MEMCACHE_ASCII);
    ASSERT(state >= SW_START && state < SW_SENTINEL);
    ASSERT(b != NULL);
    ASSERT(b->pos <= b->last);

    /* validate the parsing marker */
    ASSERT(r->pos != NULL);
    ASSERT(r->pos >= b->pos && r->pos <= b->last);

    for (p = r->pos; p < b->last; p++) {
        ch = *p;

        switch (state) {
        case SW_START:
            if (isdigit(ch)) {
                state = SW_RSP_NUM;
            } else {
                state = SW_RSP_STR;
            }
            p = p - 1; /* go back by 1 byte */

            break;

        case SW_RSP_NUM:
            if (r->token == NULL) {
                /* rsp_start <- p; type_start <- p */
                r->token = p;
            }

            if (isdigit(ch)) {
                /* num <- num * 10 + (ch - '0') */
                ;
            } else if (ch == ' ' || ch == CR) {
                /* type_end <- p - 1 */
                r->token = NULL;
                r->type = MSG_RSP_MC_NUM;
                p = p - 1; /* go back by 1 byte */
                state = SW_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RSP_STR:
            if (r->token == NULL) {
                /* rsp_start <- p; type_start <- p */
                r->token = p;
            }

            if (ch == ' ' || ch == CR) {
                /* type_end <- p - 1 */
                m = r->token;
                r->token = NULL;
                r->type = MSG_UNKNOWN;

                switch (p - m) {
                case 3:
                    if (str4cmp(m, 'E', 'N', 'D', '\r')) {
                        r->type = MSG_RSP_MC_END;
                        /* end_start <- m; end_end <- p - 1*/
                        r->end = m;
                        break;
                    }

                    break;

                case 5:
                    if (str5cmp(m, 'V', 'A', 'L', 'U', 'E')) {
                        /*
                         * Encompasses responses for 'get', 'gets' and
                         * 'cas' command.
                         */
                        r->type = MSG_RSP_MC_VALUE;
                        break;
                    }

                    if (str5cmp(m, 'E', 'R', 'R', 'O', 'R')) {
                        r->type = MSG_RSP_MC_ERROR;
                        break;
                    }

                    break;

                case 6:
                    if (str6cmp(m, 'S', 'T', 'O', 'R', 'E', 'D')) {
                        r->type = MSG_RSP_MC_STORED;
                        break;
                    }

                    if (str6cmp(m, 'E', 'X', 'I', 'S', 'T', 'S')) {
                        r->type = MSG_RSP_MC_EXISTS;
                        break;
                    }

                    break;

                case 7:
                    if (str7cmp(m, 'D', 'E', 'L', 'E', 'T', 'E', 'D')) {
                        r->type = MSG_RSP_MC_DELETED;
                        break;
                    }

                    break;

                case 9:
                    if (str9cmp(m, 'N', 'O', 'T', '_', 'F', 'O', 'U', 'N', 'D')) {
                        r->type = MSG_RSP_MC_NOT_FOUND;
                        break;
                    }

                    break;

                case 10:
                    if (str10cmp(m, 'N', 'O', 'T', '_', 'S', 'T', 'O', 'R', 'E', 'D')) {
                        r->type = MSG_RSP_MC_NOT_STORED;
                        break;
                    }

                    break;

                case 12:
                    if (str12cmp(m, 'C', 'L', 'I', 'E', 'N', 'T', '_', 'E', 'R', 'R', 'O', 'R')) {
                        r->type = MSG_RSP_MC_CLIENT_ERROR;
                        break;
                    }

                    if (str12cmp(m, 'S', 'E', 'R', 'V', 'E', 'R', '_', 'E', 'R', 'R', 'O', 'R')) {
                        r->type = MSG_RSP_MC_SERVER_ERROR;
                        break;
                    }

                    break;
                }

                switch (r->type) {
                case MSG_UNKNOWN:
                    goto error;

                case MSG_RSP_MC_STORED:
                case MSG_RSP_MC_NOT_STORED:
                case MSG_RSP_MC_EXISTS:
                case MSG_RSP_MC_NOT_FOUND:
                case MSG_RSP_MC_DELETED:
                    state = SW_CRLF;
                    break;

                case MSG_RSP_MC_END:
                    state = SW_CRLF;
                    break;

                case MSG_RSP_MC_VALUE:
                    state = SW_SPACES_BEFORE_KEY;
                    break;

                case MSG_RSP_MC_ERROR:
                    state = SW_CRLF;
                    break;

                case MSG_RSP_MC_CLIENT_ERROR:
                case MSG_RSP_MC_SERVER_ERROR:
                    state = SW_RUNTO_CRLF;
                    break;

                default:
                    NOT_REACHED();
                }

                p = p - 1; /* go back by 1 byte */
            }

            break;

        case SW_SPACES_BEFORE_KEY:
            if (ch != ' ') {
                state = SW_KEY;
                p = p - 1; /* go back by 1 byte */
            }

            break;

        case SW_KEY:
            if (r->token == NULL) {
                r->token = p;
                r->key_start = p;
            }

            if (ch == ' ') {
                if ((p - r->key_start) > MEMCACHE_MAX_KEY_LENGTH) {
                    log_error("parsed bad req %"PRIu64" of type %d with key "
                              "prefix '%.*s...' and length %d that exceeds "
                              "maximum key length", r->id, r->type, 16,
                              r->key_start, p - r->key_start);
                    goto error;
                }
                r->key_end = p;
                r->token = NULL;
                state = SW_SPACES_BEFORE_FLAGS;
            }

            break;

        case SW_SPACES_BEFORE_FLAGS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                state = SW_FLAGS;
                p = p - 1; /* go back by 1 byte */
            }

            break;

        case SW_FLAGS:
            if (r->token == NULL) {
                /* flags_start <- p */
                r->token = p;
            }

            if (isdigit(ch)) {
                /* flags <- flags * 10 + (ch - '0') */
                ;
            } else if (ch == ' ') {
                /* flags_end <- p - 1 */
                r->token = NULL;
                state = SW_SPACES_BEFORE_VLEN;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_VLEN:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                p = p - 1; /* go back by 1 byte */
                state = SW_VLEN;
            }

            break;

        case SW_VLEN:
            if (r->token == NULL) {
                /* vlen_start <- p */
                r->token = p;
                r->vlen = (uint32_t)(ch - '0');
            } else if (isdigit(ch)) {
                r->vlen = r->vlen * 10 + (uint32_t)(ch - '0');
            } else if (ch == ' ' || ch == CR) {
                /* vlen_end <- p - 1 */
                p = p - 1; /* go back by 1 byte */
                r->token = NULL;
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RUNTO_VAL:
            switch (ch) {
            case LF:
                /* val_start <- p + 1 */
                state = SW_VAL;
                break;

            default:
                goto error;
            }

            break;

        case SW_VAL:
            m = p + r->vlen;
            if (m >= b->last) {
                ASSERT(r->vlen >= (uint32_t)(b->last - p));
                r->vlen -= (uint32_t)(b->last - p);
                m = b->last - 1;
                p = m; /* move forward by vlen bytes */
                break;
            }
            switch (*m) {
            case CR:
                /* val_end <- p - 1 */
                p = m; /* move forward by vlen bytes */
                state = SW_VAL_LF;
                break;

            default:
                goto error;
            }

            break;

        case SW_VAL_LF:
            switch (ch) {
            case LF:
                state = SW_END;
                break;

            default:
                goto error;
            }

            break;

        case SW_END:
            if (r->token == NULL) {
                if (ch != 'E') {
                    goto error;
                }
                /* end_start <- p */
                r->token = p;
            } else if (ch == CR) {
                /* end_end <- p */
                m = r->token;
                r->token = NULL;

                switch (p - m) {
                case 3:
                    if (str4cmp(m, 'E', 'N', 'D', '\r')) {
                        r->end = m;
                        state = SW_ALMOST_DONE;
                    }
                    break;

                default:
                    goto error;
                }
            }

            break;

        case SW_RUNTO_CRLF:
            switch (ch) {
            case CR:
                if (r->type == MSG_RSP_MC_VALUE) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }

                break;

            default:
                break;
            }

            break;

        case SW_CRLF:
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_ALMOST_DONE:
            switch (ch) {
            case LF:
                /* rsp_end <- p */
                goto done;

            default:
                goto error;
            }

            break;

        case SW_SENTINEL:
        default:
            NOT_REACHED();
            break;

        }
    }

    ASSERT(p == b->last);
    r->pos = p;
    r->state = state;

    if (b->last == b->end && r->token != NULL) {
        r->pos = r->token;
        r->token = NULL;
        r->result = MSG_PARSE_REPAIR;
    } else {
        r->result = MSG_PARSE_AGAIN;
    }

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed rsp %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

done:
    ASSERT(r->type > MSG_UNKNOWN && r->type < MSG_SENTINEL);
    r->pos = p + 1;
    ASSERT(r->pos <= b->last);
    r->state = SW_START;
    r->token = NULL;
    r->result = MSG_PARSE_OK;

    log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed rsp %"PRIu64" res %d "
                "type %d state %d rpos %d of %d", r->id, r->result, r->type,
                r->state, r->pos - b->pos, b->last - b->pos);
    return;

error:
    r->result = MSG_PARSE_ERROR;
    r->state = state;
    errno = EINVAL;

    log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "parsed bad rsp %"PRIu64" "
                "res %d type %d state %d", r->id, r->result, r->type,
                r->state);
}
char *
conf_add_server(struct conf *cf, struct command *cmd, void *conf)
{
    rstatus_t status;
    struct array *a;
    struct string *value;
    struct conf_server *field;
    uint8_t *p, *q, *start;
    uint8_t *pname, *addr, *port, *weight, *name;
    uint32_t k, delimlen, pnamelen, addrlen, portlen, weightlen, namelen;
    char delim[] = " ::";

    p = conf;
    a = (struct array *)(p + cmd->offset);

    field = array_push(a);
    if (field == NULL) {
        return CONF_ERROR;
    }

    conf_server_init(field);

    value = array_top(&cf->arg);

    /* parse "hostname:port:weight [name]" or "/path/unix_socket:weight [name]" from the end */
    p = value->data + value->len - 1;
    start = value->data;
    addr = NULL;
    addrlen = 0;
    weight = NULL;
    weightlen = 0;
    port = NULL;
    portlen = 0;
    name = NULL;
    namelen = 0;

    delimlen = value->data[0] == '/' ? 2 : 3;

    for (k = 0; k < sizeof(delim); k++) {
        q = nc_strrchr(p, start, delim[k]);
        if (q == NULL) {
            if (k == 0) {
                /*
                 * name in "hostname:port:weight [name]" format string is
                 * optional
                 */
                continue;
            }
            break;
        }

        switch (k) {
        case 0:
            name = q + 1;
            namelen = (uint32_t)(p - name + 1);
            break;

        case 1:
            weight = q + 1;
            weightlen = (uint32_t)(p - weight + 1);
            break;

        case 2:
            port = q + 1;
            portlen = (uint32_t)(p - port + 1);
            break;

        default:
            NOT_REACHED();
        }

        p = q - 1;
    }

    if (k != delimlen) {
        return "has an invalid \"hostname:port:weight [name]\"or \"/path/unix_socket:weight [name]\" format string";
    }

    pname = value->data;
    pnamelen = namelen > 0 ? value->len - (namelen + 1) : value->len;
    status = string_copy(&field->pname, pname, pnamelen);
    if (status != NC_OK) {
        array_pop(a);
        return CONF_ERROR;
    }

    addr = start;
    addrlen = (uint32_t)(p - start + 1);

    field->weight = nc_atoi(weight, weightlen);
    if (field->weight < 0) {
        return "has an invalid weight in \"hostname:port:weight [name]\" format string";
    } else if (field->weight == 0) {
        return "has a zero weight in \"hostname:port:weight [name]\" format string";
    }

    if (value->data[0] != '/') {
        field->port = nc_atoi(port, portlen);
        if (field->port < 0 || !nc_valid_port(field->port)) {
            return "has an invalid port in \"hostname:port:weight [name]\" format string";
        }
    }

    if (name == NULL) {
        /*
         * To maintain backward compatibility with libmemcached, we don't
         * include the port as the part of the input string to the consistent
         * hashing algorithm, when it is equal to 11211.
         */
        if (field->port == CONF_DEFAULT_KETAMA_PORT) {
            name = addr;
            namelen = addrlen;
        } else {
            name = addr;
            namelen = addrlen + 1 + portlen;
        }
    }

    status = string_copy(&field->name, name, namelen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    status = string_copy(&field->addrstr, addr, addrlen);
    if (status != NC_OK) {
        return CONF_ERROR;
    }

    /*
     * The address resolution of the backend server hostname is lazy.
     * The resolution occurs when a new connection to the server is
     * created, which could either be the first time or every time
     * the server gets re-added to the pool after an auto ejection
     */

    field->valid = 1;

    return CONF_OK;
}
Exemple #25
0
static void
call_make_arithmetic_req(struct context *ctx, struct call *call,
                         uint32_t key_id, long int key_vlen)
{
    struct opt *opt = &ctx->opt;
    int len;
    uint32_t i;

    for (i = 0; i < REQ_IOV_LEN; i++) {
        struct iovec *iov = &call->req.iov[i];

        switch (i) {
        case REQ_IOV_METHOD:
            iov->iov_base = req_strings[opt->method].data;
            iov->iov_len = req_strings[opt->method].len;
            break;

        case REQ_IOV_KEY:
            len = mcp_scnprintf(call->req.keyname, sizeof(call->req.keyname),
                                "%.*s%08"PRIx32" ", opt->prefix.len,
                                opt->prefix.data, key_id);
            iov->iov_base = call->req.keyname;
            iov->iov_len = (size_t)len;
            break;

        case REQ_IOV_FLAG:
            iov->iov_base = NULL;
            iov->iov_len = 0;
            break;

        case REQ_IOV_EXPIRY:
            /* use expiry iov as incr/decr value */
            len = mcp_scnprintf(call->req.expiry, sizeof(call->req.expiry),
                                "%ld ", key_vlen);
            iov->iov_base = call->req.expiry;
            iov->iov_len = (size_t)len;
            break;

        case REQ_IOV_VLEN:
        case REQ_IOV_CAS:
            iov->iov_base = NULL;
            iov->iov_len = 0;
            break;

        case REQ_IOV_NOREPLY:
            if (opt->use_noreply) {
                iov->iov_base = msg_strings[MSG_NOREPLY].data;
                iov->iov_len = msg_strings[MSG_NOREPLY].len;
                call->req.noreply = 1;
            } else {
                iov->iov_base = NULL;
                iov->iov_len = 0;
                call->req.noreply = 0;
            }
            break;

        case REQ_IOV_CRLF:
            iov->iov_base = msg_strings[MSG_CRLF].data;
            iov->iov_len = msg_strings[MSG_CRLF].len;
            break;

        case REQ_IOV_VALUE:
        case REQ_IOV_CRLF2:
            iov->iov_base = NULL;
            iov->iov_len = 0;
            break;

        default:
            NOT_REACHED();
        }
        call->req.send += iov->iov_len;
    }
}
static rstatus_t
conf_parse_core(struct conf *cf, void *data)
{
    rstatus_t status;
    bool done, leaf, new_pool;

    ASSERT(cf->sound);

    status = conf_event_next(cf);
    if (status != NC_OK) {
        return status;
    }

    log_debug(LOG_VVERB, "next event %d depth %"PRIu32" seq %d", cf->event.type,
              cf->depth, cf->seq);

    done = false;
    leaf = false;
    new_pool = false;

    switch (cf->event.type) {
    case YAML_MAPPING_END_EVENT:
        cf->depth--;
        if (cf->depth == 1) {
            conf_pop_scalar(cf);
        } else if (cf->depth == 0) {
            done = true;
        }
        break;

    case YAML_MAPPING_START_EVENT:
        cf->depth++;
        break;

    case YAML_SEQUENCE_START_EVENT:
        cf->seq = 1;
        break;

    case YAML_SEQUENCE_END_EVENT:
        conf_pop_scalar(cf);
        cf->seq = 0;
        break;

    case YAML_SCALAR_EVENT:
        status = conf_push_scalar(cf);
        if (status != NC_OK) {
            break;
        }

        /* take appropriate action */
        if (cf->seq) {
            /* for a sequence, leaf is at CONF_MAX_DEPTH */
            ASSERT(cf->depth == CONF_MAX_DEPTH);
            leaf = true;
        } else if (cf->depth == CONF_ROOT_DEPTH) {
            /* create new conf_pool */
            data = array_push(&cf->pool);
            if (data == NULL) {
                status = NC_ENOMEM;
                break;
           }
           new_pool = true;
        } else if (array_n(&cf->arg) == cf->depth + 1) {
            /* for {key: value}, leaf is at CONF_MAX_DEPTH */
            ASSERT(cf->depth == CONF_MAX_DEPTH);
            leaf = true;
        }
        break;

    default:
        NOT_REACHED();
        break;
    }

    conf_event_done(cf);

    if (status != NC_OK) {
        return status;
    }

    if (done) {
        /* terminating condition */
        return NC_OK;
    }

    if (leaf || new_pool) {
        status = conf_handler(cf, data);

        if (leaf) {
            conf_pop_scalar(cf);
            if (!cf->seq) {
                conf_pop_scalar(cf);
            }
        }

        if (status != NC_OK) {
            return status;
        }
    }

    return conf_parse_core(cf, data);
}
int
Unicode_CompareRange(const char *str1,         // IN:
                     UnicodeIndex str1Start,   // IN:
                     UnicodeIndex str1Length,  // IN:
                     const char *str2,         // IN:
                     UnicodeIndex str2Start,   // IN:
                     UnicodeIndex str2Length,  // IN:
                     Bool ignoreCase)          // IN:
{
   int result = -1;
   char *substr1 = NULL;
   char *substr2 = NULL;
   utf16_t *substr1UTF16 = NULL;
   utf16_t *substr2UTF16 = NULL;
   UnicodeIndex i = 0;
   UnicodeIndex utf16Index;
   utf16_t codeUnit1;
   utf16_t codeUnit2;
   uint32 codePoint1;
   uint32 codePoint2;

   /*
    * TODO: Allocating substrings is a performance hit.  We should do this
    * search in-place.  (However, searching UTF-8 requires tender loving
    * care, and it's just easier to search UTF-16.)
    */

   substr1 = Unicode_Substr(str1, str1Start, str1Length);
   if (!substr1) {
      goto out;
   }

   substr2 = Unicode_Substr(str2, str2Start, str2Length);
   if (!substr2) {
      goto out;
   }

   /*
    * XXX TODO: Need to normalize the incoming strings to NFC or NFD.
    */

   substr1UTF16 = Unicode_GetAllocUTF16(substr1);
   if (!substr1UTF16) {
      goto out;
   }

   substr2UTF16 = Unicode_GetAllocUTF16(substr2);
   if (!substr2UTF16) {
      goto out;
   }

   /*
    * TODO: This is the naive string search algorithm, which is O(n * m). We
    * can do better with KMP or Boyer-Moore if this proves to be a bottleneck.
    */

   while (TRUE) {
      codeUnit1 = *(substr1UTF16 + i);
      codeUnit2 = *(substr2UTF16 + i);

      /*
       * TODO: Simple case folding doesn't handle the situation where more
       * than one code unit is needed to store the result of the case folding.
       *
       * This means that German "straBe" (where B = sharp S, U+00DF) will not
       * match "STRASSE", even though the two strings are the same.
       */

      if (ignoreCase) {
         codeUnit1 = UnicodeSimpleCaseFold(codeUnit1);
         codeUnit2 = UnicodeSimpleCaseFold(codeUnit2);
      }

      if (codeUnit1 != codeUnit2) {
         break;
      }

      if (codeUnit1 == 0) {
         // End of both strings reached: strings are equal.
         result = 0;
         goto out;
      }

      i++;
   }

   /*
    * The two UTF-16 code units differ. If they're the first code unit of a
    * surrogate pair (for Unicode values past U+FFFF), decode the surrogate
    * pair into a full Unicode code point.
    */

   if (U16_IS_SURROGATE(codeUnit1)) {
      ssize_t substrUTF16Len = Unicode_UTF16Strlen(substr1UTF16);

      // U16_NEXT modifies the index, so let it work on a copy.
      utf16Index = i;

      // Decode the surrogate if needed.
      U16_NEXT(substr1UTF16, utf16Index, substrUTF16Len, codePoint1);
   } else {
      // Not a surrogate?  Then the code point value is the code unit.
      codePoint1 = codeUnit1;
   }

   if (U16_IS_SURROGATE(codeUnit2)) {
      ssize_t substrUTF16Len = Unicode_UTF16Strlen(substr2UTF16);

      utf16Index = i;
      U16_NEXT(substr2UTF16, utf16Index, substrUTF16Len, codePoint2);
   } else {
      codePoint2 = codeUnit2;
   }

   if (codePoint1 < codePoint2) {
      result = -1;
   } else if (codePoint1 > codePoint2) {
      result = 1;
   } else {
      // If we hit the end of the string, we've already gone to 'out'.
      NOT_REACHED();
   }

  out:
   free(substr1UTF16);
   free(substr2UTF16);

   free(substr1);
   free(substr2);

   return result;
}
static rstatus_t
conf_validate_structure(struct conf *cf)
{
    rstatus_t status;
    int type, depth;
    uint32_t i, count[CONF_MAX_DEPTH + 1];
    bool done, error, seq;

    status = conf_yaml_init(cf);
    if (status != NC_OK) {
        return status;
    }

    done = false;
    error = false;
    seq = false;
    depth = 0;
    for (i = 0; i < CONF_MAX_DEPTH + 1; i++) {
        count[i] = 0;
    }

    /*
     * Validate that the configuration conforms roughly to the following
     * yaml tree structure:
     *
     * keyx:
     *   key1: value1
     *   key2: value2
     *   seq:
     *     - elem1
     *     - elem2
     *     - elem3
     *   key3: value3
     *
     * keyy:
     *   key1: value1
     *   key2: value2
     *   seq:
     *     - elem1
     *     - elem2
     *     - elem3
     *   key3: value3
     */
    do {
        status = conf_event_next(cf);
        if (status != NC_OK) {
            return status;
        }

        type = cf->event.type;

        log_debug(LOG_VVERB, "next event %d depth %d seq %d", type, depth, seq);

        switch (type) {
        case YAML_STREAM_START_EVENT:
        case YAML_DOCUMENT_START_EVENT:
            break;

        case YAML_DOCUMENT_END_EVENT:
            break;

        case YAML_STREAM_END_EVENT:
            done = true;
            break;

        case YAML_MAPPING_START_EVENT:
            if (depth == CONF_ROOT_DEPTH && count[depth] != 1) {
                error = true;
                log_error("conf: '%s' has more than one \"key:value\" at depth"
                          " %d", cf->fname, depth);
            } else if (depth >= CONF_MAX_DEPTH) {
                error = true;
                log_error("conf: '%s' has a depth greater than %d", cf->fname,
                          CONF_MAX_DEPTH);
            }
            depth++;
            break;

        case YAML_MAPPING_END_EVENT:
            if (depth == CONF_MAX_DEPTH) {
                if (seq) {
                    seq = false;
                } else {
                    error = true;
                    log_error("conf: '%s' missing sequence directive at depth "
                              "%d", cf->fname, depth);
                }
            }
            depth--;
            count[depth] = 0;
            break;

        case YAML_SEQUENCE_START_EVENT:
            if (seq) {
                error = true;
                log_error("conf: '%s' has more than one sequence directive",
                          cf->fname);
            } else if (depth != CONF_MAX_DEPTH) {
                error = true;
                log_error("conf: '%s' has sequence at depth %d instead of %d",
                          cf->fname, depth, CONF_MAX_DEPTH);
            } else if (count[depth] != 1) {
                error = true;
                log_error("conf: '%s' has invalid \"key:value\" at depth %d",
                          cf->fname, depth);
            }
            seq = true;
            break;

        case YAML_SEQUENCE_END_EVENT:
            ASSERT(depth == CONF_MAX_DEPTH);
            count[depth] = 0;
            break;

        case YAML_SCALAR_EVENT:
            if (depth == 0) {
                error = true;
                log_error("conf: '%s' has invalid empty \"key:\" at depth %d",
                          cf->fname, depth);
            } else if (depth == CONF_ROOT_DEPTH && count[depth] != 0) {
                error = true;
                log_error("conf: '%s' has invalid mapping \"key:\" at depth %d",
                          cf->fname, depth);
            } else if (depth == CONF_MAX_DEPTH && count[depth] == 2) {
                /* found a "key: value", resetting! */
                count[depth] = 0;
            }
            count[depth]++;
            break;

        default:
            NOT_REACHED();
        }

        conf_event_done(cf);
    } while (!done && !error);

    conf_yaml_deinit(cf);

    return !error ? NC_OK : NC_ERROR;
}
Exemple #29
0
Variant UserFSNode::invoke(const Func* func, const String& name,
                           const Array& args, bool& invoked) {
  JIT::VMRegAnchor _;

  // Assume failure
  invoked = false;

  // Public method, no private ancestor, no need for further checks (common)
  if (func &&
      !(func->attrs() & (AttrPrivate|AttrProtected|AttrAbstract)) &&
      !func->hasPrivateAncestor()) {
    Variant ret;
    g_context->invokeFunc(ret.asTypedValue(), func, args, m_obj.get());
    invoked = true;
    return ret;
  }

  // No explicitly defined function, no __call() magic method
  // Give up.
  if (!func && !m_Call) {
    return uninit_null();
  }

  HPHP::JIT::CallerFrame cf;
  Class* ctx = arGetContextClass(cf());
  switch(g_context->lookupObjMethod(func, m_cls, name.get(), ctx)) {
    case LookupResult::MethodFoundWithThis:
    {
      Variant ret;
      g_context->invokeFunc(ret.asTypedValue(), func, args, m_obj.get());
      invoked = true;
      return ret;
    }

    case LookupResult::MagicCallFound:
    {
      Variant ret;
      g_context->invokeFunc(ret.asTypedValue(), func,
                              make_packed_array(name, args), m_obj.get());
      invoked = true;
      return ret;
    }

    case LookupResult::MethodNotFound:
      // There's a method somewhere in the hierarchy, but none
      // which are accessible.
      /* fallthrough */
    case LookupResult::MagicCallStaticFound:
      // We're not calling statically, so this result is unhelpful
      // Also, it's never produced by lookupObjMethod, so it'll
      // never happen, but we must handle all enums
      return uninit_null();

    case LookupResult::MethodFoundNoThis:
      // Should never happen (Attr::Static check in ctor)
      assert(false);
      raise_error("%s::%s() must not be declared static",
                  m_cls->name()->data(), name.data());
      return uninit_null();
  }

  NOT_REACHED();
  return uninit_null();
}
Exemple #30
0
Unicode
Unicode_Normalize(ConstUnicode str,              // IN
                  UnicodeNormalizationForm form) // IN
{
   UNormalizationMode mode;
   UChar *uchars;
   Unicode result;
   int32_t normalizedLen;
   UErrorCode status = U_ZERO_ERROR;
   UCharIterator strIter;
   UBool neededToNormalize = FALSE;

   uiter_setUTF8(&strIter, (const char *)str, -1);

   switch (form) {
   case UNICODE_NORMAL_FORM_C:
      mode = UNORM_NFC;
      break;
   case UNICODE_NORMAL_FORM_D:
      mode = UNORM_NFD;
      break;
   default:
      NOT_REACHED();
   }

   normalizedLen = unorm_next(&strIter,
                              NULL,
                              0,
                              mode,
                              0,
                              TRUE,
                              &neededToNormalize,
                              &status);

   if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) {
      // We expect U_BUFFER_OVERFLOW_ERROR here. Anything else is a problem.
      ASSERT(U_SUCCESS(status));
      return NULL;
   }

   uchars = Util_SafeMalloc(sizeof *uchars * normalizedLen);

   // Reset back to the beginning of the UTF-8 input.
   (*strIter.move)(&strIter, 0, UITER_START);

   status = U_ZERO_ERROR;
   normalizedLen = unorm_next(&strIter,
                              uchars,
                              normalizedLen,
                              mode,
                              0,
                              TRUE,
                              &neededToNormalize,
                              &status);

   if (U_FAILURE(status)) {
      ASSERT(U_SUCCESS(status));
      return NULL;
   }

   result = Unicode_AllocWithLength(uchars,
                                    normalizedLen * 2,
                                    STRING_ENCODING_UTF16);
   free(uchars);

   return result;
}