Exemple #1
0
/*
 *  ======== cmm_get_info ========
 *  Purpose:
 *      Return the current memory utilization information.
 */
int cmm_get_info(struct cmm_object *hcmm_mgr,
			OUT struct cmm_info *cmm_info_obj)
{
	struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
	u32 ul_seg;
	int status = 0;
	struct cmm_allocator *altr;
	struct cmm_mnode *mnode_obj = NULL;

	DBC_REQUIRE(cmm_info_obj != NULL);

	if (!hcmm_mgr) {
		status = -EFAULT;
		return status;
	}
	mutex_lock(&cmm_mgr_obj->cmm_lock);
	cmm_info_obj->ul_num_gppsm_segs = 0;	/* # of SM segments */
	/* Total # of outstanding alloc */
	cmm_info_obj->ul_total_in_use_cnt = 0;
	/* min block size */
	cmm_info_obj->ul_min_block_size = cmm_mgr_obj->ul_min_block_size;
	/* check SM memory segments */
	for (ul_seg = 1; ul_seg <= CMM_MAXGPPSEGS; ul_seg++) {
		/* get the allocator object for this segment id */
		altr = get_allocator(cmm_mgr_obj, ul_seg);
		if (altr != NULL) {
			cmm_info_obj->ul_num_gppsm_segs++;
			cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_pa =
			    altr->shm_base - altr->ul_dsp_size;
			cmm_info_obj->seg_info[ul_seg - 1].ul_total_seg_size =
			    altr->ul_dsp_size + altr->ul_sm_size;
			cmm_info_obj->seg_info[ul_seg - 1].dw_gpp_base_pa =
			    altr->shm_base;
			cmm_info_obj->seg_info[ul_seg - 1].ul_gpp_size =
			    altr->ul_sm_size;
			cmm_info_obj->seg_info[ul_seg - 1].dw_dsp_base_va =
			    altr->dw_dsp_base;
			cmm_info_obj->seg_info[ul_seg - 1].ul_dsp_size =
			    altr->ul_dsp_size;
			cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_va =
			    altr->dw_vm_base - altr->ul_dsp_size;
			cmm_info_obj->seg_info[ul_seg - 1].ul_in_use_cnt = 0;
			mnode_obj = (struct cmm_mnode *)
			    lst_first(altr->in_use_list_head);
			/* Count inUse blocks */
			while (mnode_obj) {
				cmm_info_obj->ul_total_in_use_cnt++;
				cmm_info_obj->seg_info[ul_seg -
						       1].ul_in_use_cnt++;
				/* next node. */
				mnode_obj = (struct cmm_mnode *)
				    lst_next(altr->in_use_list_head,
					     (struct list_head *)mnode_obj);
			}
		}
	}			/* end for */
	mutex_unlock(&cmm_mgr_obj->cmm_lock);
	return status;
}
Exemple #2
0
/*
 *  ======== un_register_gppsm_seg ========
 *  Purpose:
 *      UnRegister the SM allocator by freeing all its resources and
 *      nulling cmm mgr table entry.
 *  Note:
 *      This routine is always called within cmm lock crit sect.
 */
static void un_register_gppsm_seg(struct cmm_allocator *psma)
{
	struct cmm_mnode *mnode_obj = NULL;
	struct cmm_mnode *next_node = NULL;

	DBC_REQUIRE(psma != NULL);
	if (psma->free_list_head != NULL) {
		/* free nodes on free list */
		mnode_obj = (struct cmm_mnode *)lst_first(psma->free_list_head);
		while (mnode_obj) {
			next_node =
			    (struct cmm_mnode *)lst_next(psma->free_list_head,
							 (struct list_head *)
							 mnode_obj);
			lst_remove_elem(psma->free_list_head,
					(struct list_head *)mnode_obj);
			kfree((void *)mnode_obj);
			/* next node. */
			mnode_obj = next_node;
		}
		kfree(psma->free_list_head);	/* delete freelist */
		/* free nodes on InUse list */
		mnode_obj =
		    (struct cmm_mnode *)lst_first(psma->in_use_list_head);
		while (mnode_obj) {
			next_node =
			    (struct cmm_mnode *)lst_next(psma->in_use_list_head,
							 (struct list_head *)
							 mnode_obj);
			lst_remove_elem(psma->in_use_list_head,
					(struct list_head *)mnode_obj);
			kfree((void *)mnode_obj);
			/* next node. */
			mnode_obj = next_node;
		}
		kfree(psma->in_use_list_head);	/* delete InUse list */
	}
	if ((void *)psma->dw_vm_base != NULL)
		MEM_UNMAP_LINEAR_ADDRESS((void *)psma->dw_vm_base);

	/* Free allocator itself */
	kfree(psma);
}
Exemple #3
0
void
main (void)
{
  LIST *list;
  int done = 0;
  REC *rec;
  char line[80];

  list = lst_init ();

  printf ("Type a list of names and ages. Empty line quits\n\n");

  while (!done)
    {
      rec = lst_newnode (sizeof (REC));
      gets (line);
      if ((done = (line[0] == '\0')) != 1)
	{
	  strcpy (rec->name, line);
	  gets (line);
	  rec->age = atoi (line);
	  lst_insertafter (list, rec, LST_HEAD (list));
	}
    };

  printf ("\nThe list you typed in was:\n\n");

  for (rec = lst_first (list); rec; rec = lst_next (rec))
    printf ("Name: %s, Age: %d\n", rec->name, rec->age);

  printf ("\nSorting the list...\n\n");

  lst_mergesort (list, my_cmp);

  for (rec = lst_first (list); rec; rec = lst_next (rec))
    printf ("Name: %s, Age: %d\n", rec->name, rec->age);

  lst_kill (list, lst_freenode);
}
Exemple #4
0
/*
 *  ======== dev_notify_clients ========
 *  Purpose:
 *      Notify all clients of this device of a change in device status.
 */
int dev_notify_clients(struct dev_object *hdev_obj, u32 ret)
{
	int status = 0;

	struct dev_object *dev_obj = hdev_obj;
	void *proc_obj;

	for (proc_obj = (void *)lst_first(dev_obj->proc_list);
	     proc_obj != NULL;
	     proc_obj = (void *)lst_next(dev_obj->proc_list,
					 (struct list_head *)proc_obj))
		proc_notify_clients(proc_obj, (u32) ret);

	return status;
}
Exemple #5
0
/*
 *  ======== rmm_free ========
 */
bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size,
	      bool reserved)
{
	struct rmm_ovly_sect *sect;
	bool ret = true;

	DBC_REQUIRE(target);

	DBC_REQUIRE(reserved || segid < target->num_segs);
	DBC_REQUIRE(reserved || (dsp_addr >= target->seg_tab[segid].base &&
				 (dsp_addr + size) <= (target->seg_tab[segid].
						   base +
						   target->seg_tab[segid].
						   length)));

	/*
	 *  Free or unreserve memory.
	 */
	if (!reserved) {
		ret = free_block(target, segid, dsp_addr, size);
		if (ret)
			target->seg_tab[segid].number--;

	} else {
		/* Unreserve memory */
		sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list);
		while (sect != NULL) {
			if (dsp_addr == sect->addr) {
				DBC_ASSERT(size == sect->size);
				/* Remove from list */
				lst_remove_elem(target->ovly_list,
						(struct list_head *)sect);
				kfree(sect);
				break;
			}
			sect =
			    (struct rmm_ovly_sect *)lst_next(target->ovly_list,
							     (struct list_head
							      *)sect);
		}
		if (sect == NULL)
			ret = false;

	}
	return ret;
}
Exemple #6
0
/*
 *  ======== cmm_free_buf ========
 *  Purpose:
 *      Free the given buffer.
 */
int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa,
			u32 ul_seg_id)
{
	struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
	int status = -EFAULT;
	struct cmm_mnode *mnode_obj = NULL;
	struct cmm_allocator *allocator = NULL;
	struct cmm_attrs *pattrs;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(buf_pa != NULL);

	if (ul_seg_id == 0) {
		pattrs = &cmm_dfltalctattrs;
		ul_seg_id = pattrs->ul_seg_id;
	}
	if (!hcmm_mgr || !(ul_seg_id > 0)) {
		status = -EFAULT;
		return status;
	}
	/* get the allocator for this segment id */
	allocator = get_allocator(cmm_mgr_obj, ul_seg_id);
	if (allocator != NULL) {
		mutex_lock(&cmm_mgr_obj->cmm_lock);
		mnode_obj =
		    (struct cmm_mnode *)lst_first(allocator->in_use_list_head);
		while (mnode_obj) {
			if ((u32) buf_pa == mnode_obj->dw_pa) {
				/* Found it */
				lst_remove_elem(allocator->in_use_list_head,
						(struct list_head *)mnode_obj);
				/* back to freelist */
				add_to_free_list(allocator, mnode_obj);
				status = 0;	/* all right! */
				break;
			}
			/* next node. */
			mnode_obj = (struct cmm_mnode *)
			    lst_next(allocator->in_use_list_head,
				     (struct list_head *)mnode_obj);
		}
		mutex_unlock(&cmm_mgr_obj->cmm_lock);
	}
	return status;
}
Exemple #7
0
static void proc_apply(process_t *proc, term_t mod, term_t fun, term_t args)
{
	celem_t *ip;
	int arity = lst_len(args);

	term_t mdi = intnum(proc->mod_index);
	term_t off = intnum(proc->ip - proc->code);

	ip = code_base_lookup(proc->base,
		mod, fun, arity, &proc->mod_index, &proc->code);
	if (ip == 0)
	{
		*(term_t *)apr_array_push(proc->cstack) = args;
		*(term_t *)apr_array_push(proc->cstack) = fun;
		*(term_t *)apr_array_push(proc->cstack) = mod;

		ip = code_base_lookup(proc->base,
			A_ERROR_HANDLER, A_UNDEFINED_FUNCTION, 3, &proc->mod_index, &proc->code);
	}
	else
	{
		// pushing args in reverse order: kludgy

		term_t l;
		int i;
		for (i = 0; i < arity; i++)
			*(term_t *)apr_array_push(proc->cstack) = AI_UNDEFINED;

		l = args;
		i = 0;
		while (l != nil)
		{
			(((term_t *)proc->cstack->elts)[proc->cstack->nelts-i-1]) = lst_value(l);
			l = lst_next(l);
			i++;
		}
	}

	*(term_t *)apr_array_push(proc->cstack) = mdi;
	*(term_t *)apr_array_push(proc->cstack) = off;

	proc->ip = ip;
}
Exemple #8
0
/*
 * ====== get_free_block ========
 *  Purpose:
 *      Scan the free block list and return the first block that satisfies
 *      the size.
 */
static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator,
					u32 usize)
{
	if (allocator) {
		struct cmm_mnode *mnode_obj = (struct cmm_mnode *)
		    lst_first(allocator->free_list_head);
		while (mnode_obj) {
			if (usize <= (u32) mnode_obj->ul_size) {
				lst_remove_elem(allocator->free_list_head,
						(struct list_head *)mnode_obj);
				return mnode_obj;
			}
			/* next node. */
			mnode_obj = (struct cmm_mnode *)
			    lst_next(allocator->free_list_head,
				     (struct list_head *)mnode_obj);
		}
	}
	return NULL;
}
Exemple #9
0
static apr_status_t port_buffer_send(buffer_t *buf, term_t io)
{
	int avail;

	if (is_nil(io))
		return 0;

	avail = buffer_available(buf);
	if (is_int(io))
	{
		if (avail == 0)
			return APR_EINCOMPLETE;
		else
			buffer_put_byte(buf, int_value(io));
	}
	else if (is_binary(io))
	{
		int size = int_value2(bin_size(io));
		if (size > avail)
		{
			buffer_put_data(buf, bin_data(io), avail);
			return APR_EINCOMPLETE;
		}
		else
			buffer_put_data(buf, bin_data(io), size);
	}
	if (is_list(io))
	{
		while (is_cons(io))
		{
			apr_status_t rs;
			rs = port_buffer_send(buf, lst_value(io));
			if (rs != 0)
				return rs;
			io = lst_next(io);
		}
	}

	return APR_SUCCESS;
}
Exemple #10
0
static _linkage_block_ *
_add_line_to_linkage_block_ (Line *line_to_add,
			     Line *linkage_block_line,
			     List *linkage_block_lst)
{
  _linkage_block_ *linkage_block;

  assert (line_to_add);
  assert (linkage_block_line);
  assert (linkage_block_lst);
  assert (!lst_is_empty (linkage_block_lst));
  assert (line_to_add -> scale < linkage_block_line -> scale);

  for (linkage_block = lst_first (linkage_block_lst);
       linkage_block && linkage_block -> line != linkage_block_line;
       linkage_block = lst_next (linkage_block_lst));
  if (linkage_block && linkage_block -> line == linkage_block_line)
    {
      lst_add (line_to_add, linkage_block -> candidate_line_lst);
      linkage_block -> nb_of_candidates ++;
    }

  return linkage_block;
}
Exemple #11
0
/*
 *  ======== dev_remove_proc_object ========
 *  Purpose:
 *      Search for and remove a Proc object from the given list maintained
 *      by the DEV
 *  Parameters:
 *      p_proc_object:        Ptr to ProcObject to insert.
 *      dev_obj          Ptr to Dev Object where the list is.
 *  Returns:
 *      0:            If successful.
 *  Requires:
 *      List exists and is not empty
 *      proc_obj != 0
 *      hdev_obj is a valid Dev handle.
 *  Ensures:
 *  Details:
 *      List will be deleted when the DEV is destroyed.
 */
int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
{
	int status = -EPERM;
	struct list_head *cur_elem;
	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;

	DBC_REQUIRE(dev_obj);
	DBC_REQUIRE(proc_obj != 0);
	DBC_REQUIRE(dev_obj->proc_list != NULL);
	DBC_REQUIRE(!LST_IS_EMPTY(dev_obj->proc_list));

	/* Search list for dev_obj: */
	for (cur_elem = lst_first(dev_obj->proc_list); cur_elem != NULL;
	     cur_elem = lst_next(dev_obj->proc_list, cur_elem)) {
		/* If found, remove it. */
		if ((u32) cur_elem == proc_obj) {
			lst_remove_elem(dev_obj->proc_list, cur_elem);
			status = 0;
			break;
		}
	}

	return status;
}
Exemple #12
0
/** Get the shade determined by a given ray.
 *  
 *  @param ray the ray to trace.
 *  @param t0 the start of the interval for which to get a shade.
 *  @param t1 the end of the interval for which to get a shade.
 *  @param depth the maximum number of times a reflect ray will be
 *      cast for objects with non-NULL reflective color.
 *  @param in_trans whether the ray is inside a transparent surface or not.
 * 
 *
 *  @return the color corresponding to the closest object hit by
 *      <code>r</code> in the interval <code>[t0, t1]</code>.
 */
color_t ray_trace(ray3_t ray, float t0, float t1, int depth, bool in_trans) {
    assert(depth >= 0);

    color_t color = {0.0, 0.0, 0.0};

    if (depth == 0) return color;

    hit_record_t hit_rec, closest_hit_rec;

    // Get a hit record for the closest object that is hit.
    bool hit_something = false;
    list356_itr_t* s = lst_iterator(surfaces);
    while (lst_has_next(s)) {
        surface_t* sfc = lst_next(s);
        if (sfc_hit(sfc, &ray, t0, t1, &hit_rec)) {
            if (hit_rec.t < t1) {
                hit_something = true;
                memcpy(&closest_hit_rec, &hit_rec, 
                        sizeof(hit_record_t));
                t1 = hit_rec.t;
            }
            else assert("wrong");
        }
    }
    lst_iterator_free(s);

    // If we hit something, color the pixel.
    if (hit_something) {
        surface_t* sfc = closest_hit_rec.sfc;

        // Specular reflection.
        if (spec_reflection) {
          if (sfc->refl_color != NULL) {
              color_t refl_color = get_specular_refl(&ray,
                      &closest_hit_rec, depth, in_trans);
              add_scaled_color(&color, sfc->refl_color, &refl_color, 1.0f);
          }
        }

        // Tranparency
        if (transparency) {
          if (sfc->refr_index != -1) {
              color_t trans_color = get_transparency(&ray, &closest_hit_rec,
                      depth, !in_trans);
              // Only add returned color, don't multiply by a surface_color.
              color.red += (trans_color.red);
              color.green += (trans_color.green);
              color.blue += (trans_color.blue);
          }
        }

        // Ambient shading.
        if (ambient_shading) {
          add_scaled_color(&color, sfc->ambient_color, &ambient_light, 1.0f);
        }

        // Lighting.
        if (lighting) {
          list356_itr_t* light_itr = lst_iterator(lights);
          while (lst_has_next(light_itr)) {
              light_t* light = lst_next(light_itr);
              vector3_t light_dir;
              pv_subtract(light->position, &(closest_hit_rec.hit_pt),
                      &light_dir);
              normalize(&light_dir);

              // Check for global shadows.
              bool do_lighting = true;

              // Bool for if the shadow is caused by transparent surface.
              bool trans_shadow = false;

              ray3_t light_ray = {closest_hit_rec.hit_pt, light_dir};
              float light_dist = dist(&closest_hit_rec.hit_pt,
                      light->position);
              s = lst_iterator(surfaces);
              while (lst_has_next(s)) {
                  surface_t* sfc = lst_next(s);
                  if (sfc_hit(sfc, &light_ray, EPSILON, light_dist, &hit_rec)) {
                      do_lighting = false;
                      // If shadow is caused by transparent surface, we add
                      // Lambertian shading only so our shadows are not opaque.
                      if (hit_rec.sfc->refr_index != -1) trans_shadow = true;
                      break;
                  }
              }
              lst_iterator_free(s);
              if (!do_lighting) {
                  continue;
              }

              // Lambertian shading.
              if (lambertian_shading) {
                if (!trans_shadow) {
                    float scale = get_lambert_scale(&light_dir, &closest_hit_rec);
                    add_scaled_color(&color, sfc->diffuse_color, light->color,
                            scale);
                }
              }

            // Blin-Phong shading (if shadow is not caused by transparent
            // surface).
            if (blin_phong_shading) {
              if (!trans_shadow) {
                  float phong_scale = get_blinn_phong_scale(&ray, &light_dir,
                          &closest_hit_rec);
                  add_scaled_color(&color, sfc->spec_color, light->color, 
                          phong_scale);
              }
            }
        }

        lst_iterator_free(light_itr);
    }

    }   // if (hit_something)
    return color;
}
Exemple #13
0
/** Create a list of surfaces.
 */
list356_t* get_surfaces() {

    list356_t* surfaces = make_list() ;

    // Table.
    point3_t vertices[8] = {
        {0, 0, 1}, {8, 0, 1}, {0, 8, 1}, {8, 8, 1},
        {0, 0, -1}, {8, 0, -1}, {0, 8, -1}, {8, 8, -1},
    } ;

    int indices[] = {
        0, 1, 3,    0, 3, 2,        // top
        0, 2, 6,    0, 6, 4,        // left
        4, 6, 7,    4, 7, 5,        // bottom
        1, 5, 7,    1, 7, 3,        // right
        2, 3, 7,    2, 7, 6,        // back
        0, 4, 5,    0, 5, 1         // front
    } ;
    int top_offset = 6 ;
    int offset = 36 ;

    list356_t* table_surfaces = make_list() ;
    for (int i=0; i<top_offset/3; ++i) {
        lst_add(table_surfaces, make_triangle(
                    vertices[indices[3*i]],
                    vertices[indices[3*i+1]],
                    vertices[indices[3*i+2]],
                    &RED, &RED, &WHITE, 10.0f)) ;
    }
    for (int i=top_offset/3; i<offset/3; ++i) {
        lst_add(table_surfaces, make_triangle(
                    vertices[indices[3*i]],
                    vertices[indices[3*i+1]],
                    vertices[indices[3*i+2]],
                    &GREEN, &GREEN, &WHITE, 10.0f)) ;
    }

    // Two purple spheres.
    lst_add(table_surfaces, 
            make_sphere(6, 6, 1.75+.01, .75, 
                &PURPLE, &PURPLE, &WHITE, 100.0f)) ;
    lst_add(table_surfaces, 
            make_sphere(5, 2, 1.75+.01, .75, 
                &PURPLE, &PURPLE, &WHITE, 100.0f)) ;

    // Transparent cube.
    point3_t cube_vertices[] = {
            {4, 0, 3}, {5, 0, 3}, {4, 1, 3}, {5, 1, 3},
            {4, 0, 1.01}, {5, 0, 1.01}, {4, 1, 1.01}, {5, 1, 1.01},
    } ;
    for (int i=0; i<offset/3; ++i) {
        surface_t* t = make_triangle(
                    cube_vertices[indices[3*i]],
                    cube_vertices[indices[3*i+1]],
                    cube_vertices[indices[3*i+2]],
                    &BLACK, &BLACK, &WHITE, 10.0f) ;
        t->refr_index = 1.1f ;
        t->atten = &GREENISH ;
        lst_add(surfaces, t) ;
    }

    list356_itr_t* itr = lst_iterator(table_surfaces) ;
    while (lst_has_next(itr)) lst_add(surfaces, lst_next(itr)) ;
    lst_free(table_surfaces) ;

    // Plane at z=-1.
    surface_t* plane = make_plane(
                (point3_t){0, 0, -1},
                (point3_t){1, 0, -1},
                (point3_t){1, 1, -1},
                &LIGHT_GREY, &LIGHT_GREY, &BLACK, 10.0f) ;
    plane->refl_color = &LIGHT_GREY ;
    lst_add(surfaces, plane) ;

    return surfaces ;

}
Exemple #14
0
/*
 *  retrieves a token converted from a pp-token;
 *  ASSUMPTION: signed/unsigned integers are compatible on the host
 */
int (clx_next)(void)
{
    lex_t *t;

    clx_ppos = clx_cpos;

    while (1) {
        t = lst_next();
        clx_cpos = t->pos;
        switch(t->id) {
            case -1:
                strg_free((arena_t *)t->spell);
                break;
            case LEX_CREM:        /* %= */
            case LEX_CBAND:       /* &= */
            case LEX_CMUL:        /* *= */
            case LEX_CADD:        /* += */
            case LEX_CSUB:        /* -= */
            case LEX_CDIV:        /* /= */
            case LEX_CRSHFT:      /* >>= */
            case LEX_CLSHFT:      /* <<= */
            case LEX_CBXOR:       /* ^= */
            case LEX_CBOR:        /* |= */
            case '!':
            case '%':
            case '&':
            case LEX_INCR:        /* ++ */
            case '(':
            case ')':
            case '*':
            case '+':
            case ',':
            case '-':
            case '.':
            case '/':
            case LEX_DECR:        /* -- */
            case LEX_DEREF:       /* -> */
            case LEX_ANDAND:      /* && */
            case LEX_OROR:        /* || */
            case LEX_LEQ:         /* <= */
            case LEX_EQEQ:        /* == */
            case LEX_NEQ:         /* != */
            case LEX_GEQ:         /* >= */
            case LEX_RSHFT:       /* >> */
            case LEX_LSHFT:       /* << */
            case ':':
            case ';':
            case '<':
            case '=':
            case '>':
            case '?':
            case LEX_ELLIPSIS:    /* ... */
            case ']':
            case '[':
            case '^':
            case '{':
            case '|':
            case '}':
            case '~':
            case LEX_EOI:
                return t->id;
            case LEX_ID:
                return id(t);
            case LEX_CCON:
                {
                    int w = 0;
                    ux_t c = clx_ccon(t, &w);
                    tval.type = (w)? ty_wchartype: ty_inttype;
                    tval.u.c.v.u = c;
                    clx_sym = &tval;
                }
                return t->id;
            case LEX_SCON:
                {
                    int w = 0;
                    sz_t len = scon(t, &w);
                    tval.type = ty_array((!w)? ty_chartype: ty_wchartype, len, clx_cpos);
                    tval.u.c.v.p = xcfp(strg_sbuf);
                    clx_sym = &tval;
                }
                return t->id;
            case LEX_PPNUM:
                return ifcon(t);
            case LEX_SPACE:
            case LEX_NEWLINE:
                break;
            case LEX_SHARP:      /* # */
            case LEX_DSHARP:     /* ## */
            case LEX_UNKNOWN:
                {
                    const char *p = LEX_SPELL(t);
                    err_dpos(t->pos, (*p == '\\')? ERR_LEX_STRAYBS: ERR_LEX_UNKNOWN, p);
                }
                break;
        }
    }

    /* assert(!"impossible control flow -- should never reach here");
       return t->id; */
}
Exemple #15
0
/*
 *  recognizes character constants;
 *  ASSUMPTION: signed/unsigned integers are compatible on the host
 */
ux_t (clx_ccon)(lex_t *t, int *w)
{
    int cbyte;
    sz_t len = 0;
    const char *ss, *s, *e;
    ux_t lim, c;
#ifdef HAVE_ICONV
    iconv_t *cd;
#endif    /* HAVE_ICONV */

    assert(t);
    assert(w);
    assert(BUFUNIT > 2);
    assert(ty_wuchartype);    /* ensures types initialized */
    assert(xgeu(xmxu, TG_UCHAR_MAX));
    assert(xgeu(xmxu, TG_WUCHAR_MAX));
    assert(ir_cur);

    ss = s = LEX_SPELL(t);
    if (*s == 'L')
        *w = 1, s++;
    e = ++s;    /* skips ' */

    if (*w) {
        cbyte = ty_wchartype->size;
        assert(cbyte <= BUFUNIT);
        lim = TG_WUCHAR_MAX;
#ifdef HAVE_ICONV
        cd = main_ntow;
#endif    /* HAVE_ICONV */
    } else {
        cbyte = 1;
        lim = TG_UCHAR_MAX;
#ifdef HAVE_ICONV
        cd = main_ntoe;
#endif    /* HAVE_ICONV */
    }

    switch(*e) {
        case '\'':    /* empty; diagnosed elsewhere */
        case '\0':    /* unclosed; diagnosed elsewhere */
            return xO;
        case '\\':    /* escape sequences */
            assert(sizeof(c) >= cbyte);
            c = lex_bs(t, ss, &e, lim, "character constant");
#if HAVE_ICONV
            if (cd && !(s[1] == 'x' || (s[1] >= '0' && s[1] <= '7'))) {
                char x = xnu(c);
                ICONV_DECL(&x, 1);
                assert(xe(xiu(x), c));
                obuf = strg_sbuf, obufv = strg_sbuf;
                olen = strg_slen, olenv = strg_slen;
                ICONV_DO(cd, 1, {});
                strg_sbuf = obuf, strg_slen = olen;    /* for later reuse */
                len = strg_slen - len - olenv;
            } else {
#else    /* !HAVE_ICONV */
            {
#endif    /* HAVE_ICONV */
                if (*w)
                    memcpy(strg_sbuf, (char *)&c + ((LITTLE)? 0: sizeof(c)-cbyte), cbyte);
                else
                    strg_sbuf[0] = xnu(c);
                len = cbyte;
            }
            break;
        default:    /* ordinary chars */
#ifdef HAVE_ICONV
            if (cd) {
                do {
                    e++;
                } while(!FIRSTUTF8(*e));
                {
                    ICONV_DECL((char *)s, e - s);
                    obuf = strg_sbuf, obufv = strg_sbuf;
                    olen = strg_slen, olenv = strg_slen;
                    ICONV_DO(cd, 1, {});
                    strg_sbuf = obuf, strg_slen = olen;    /* for later reuse */
                    len = strg_slen - len - olenv;
                }
            } else {
#else    /* !HAVE_ICONV */
            {
#endif    /* HAVE_ICONV */
                assert(TG_CHAR_BIT == CHAR_BIT);
                if (*w) {
                    strg_sbuf[(LITTLE)? 0: cbyte-1] = *e;
                    memset(strg_sbuf + ((LITTLE)? 1: 0), 0, cbyte-1);
                } else
                    strg_sbuf[0] = *e;
                e++;
                len = cbyte;
            }
            break;
    }

    if (*e != '\'' && *e != '\0') {
        for (s = e; *e != '\0' && *e != '\''; e++)
            continue;
        err_dpos((FIRSTUTF8(*s))? lmap_spell(t, ss, s, e): t->pos, ERR_CONST_LARGECHAR);
    } else if (len != cbyte) {
        err_dpos(t->pos, (*w)? ERR_CONST_WIDENOTFIT: ERR_CONST_MBNOTFIT);
        return xO;
    }

    c = xO;
    memcpy(&c, strg_sbuf + ((LITTLE)? 0: sizeof(c)-cbyte), cbyte);
    if (*w) {
        switch(main_opt()->wchart) {
            case 0:    /* long */
                c = SYM_CROPSL(c);
                break;
            case 1:    /* ushort */
                c = SYM_CROPUS(c);
                break;
            case 2:    /* int */
                c = SYM_CROPSI(c);
                break;
        }
    } else    /* int from char */
        c = (main_opt()->uchar)? SYM_CROPUC(c): SYM_CROPSC(c);

    return c;
}


/*
 *  recognizes string literals
 */
static sz_t scon(lex_t *t, int *w)
{
    int cbyte;
    lex_t *n;
    sz_t clen = 0, len = 0;
    const char *ss, *s, *e;
    ux_t lim;
#ifdef HAVE_ICONV
    iconv_t *cd;
#endif

    assert(t);
    assert(w);
    assert(BUFUNIT > 2);
    assert(ty_wuchartype);    /* ensures types initialized */
    assert(xgeu(xmxu, TG_UCHAR_MAX));
    assert(xgeu(xmxu, TG_WUCHAR_MAX));
    assert(ir_cur);

    ss = s = LEX_SPELL(t);
    if (*s == 'L')
        *w = 1, s++;
    e = ++s;    /* skips " */
    while ((n = lst_peekns())->id == LEX_SCON) {
        if (*n->spell == 'L') {
            if (!*w) {    /* mb + wide = wide */
                err_dmpos(n->pos, ERR_CONST_MBWIDE, t->pos, NULL);
                err_dmpos(n->pos, ERR_CONST_MBWIDESTD, t->pos, NULL);
                *w = 2;    /* silences warnings */
            }
        } else if (*w == 1) {    /* wide + mb = wide */
            err_dmpos(n->pos, ERR_CONST_MBWIDE, t->pos, NULL);
            err_dmpos(n->pos, ERR_CONST_MBWIDESTD, t->pos, NULL);
            *w = 2;    /* silences warnings */
        }
        while ((t = lst_append(t, lst_next()))->id != LEX_SCON)
            continue;
    }
    clx_cpos = lmap_range(t->next->pos, t->pos);

    if (*w) {
        cbyte = ty_wchartype->size;
        assert(cbyte <= BUFUNIT);
        lim = TG_WUCHAR_MAX;
#ifdef HAVE_ICONV
        cd = main_ntow;
#endif    /* HAVE_ICONV */
    } else {
        cbyte = 1;
        lim = TG_UCHAR_MAX;
#ifdef HAVE_ICONV
        cd = main_ntoe;
#endif    /* HAVE_ICONV */
    }

    n = t->next;
    while (1) {
        while (1) {
            while (*e != '\\' && *e != '"' && *e != '\0')
                e++;
            if (e > s) {    /* ordinary chars */
#ifdef HAVE_ICONV
                if (cd) {
                    ICONV_DECL((char *)s, e - s);
                    obuf = strg_sbuf, obufv = strg_sbuf + len;
                    olen = strg_slen, olenv = strg_slen - len;
                    ICONV_INIT(cd);
                    ICONV_DO(cd, 0, {});
                    strg_sbuf = obuf, strg_slen = olen;    /* for later reuse */
                    len += (strg_slen - len - olenv);
                } else {
#else    /* !HAVE_ICONV */
                {
#endif    /* HAVE_ICONV */
                    sz_t d = e - s;
                    assert(TG_CHAR_BIT == CHAR_BIT);
                    while (len + (d*cbyte) > strg_slen)    /* rarely iterates */
                        MEM_RESIZE(strg_sbuf, strg_slen += BUFUNIT);
                    if (*w) {
                        while (s < e) {
                            strg_sbuf[len + ((ir_cur->f.little_endian)? 0: cbyte-1)] = *s++;
                            memset(strg_sbuf + len + ((ir_cur->f.little_endian)? 1: 0), 0,
                                   cbyte-1);
                            len += cbyte;
                        }
                    } else {
                        memcpy(&strg_sbuf[len], s, d);
                        len += d;
                    }
                }
                for (; s < e; s++)
                    if (FIRSTUTF8(*s))
                        clen++;
            }
            if (*e == '\\') {    /* escape sequences */
                ux_t c;
                assert(sizeof(c) >= cbyte);
                c = lex_bs(n, ss, &e, lim, "string literal");
#if HAVE_ICONV
                if (cd) {    /* inserts initial seq before every esc seq */
                    ICONV_DECL(NULL, 0);
                    UNUSED(ilenv);
                    UNUSED(ibufv);
                    obuf = strg_sbuf, obufv = strg_sbuf + len;
                    olen = strg_slen, olenv = strg_slen - len;
                    ICONV_INIT(cd);
                    strg_sbuf = obuf, strg_slen = olen;    /* for later reuse */
                    len += (strg_slen - len - olenv);
                }
                if (cd && !(s[1] == 'x' || (s[1] >= '0' && s[1] <= '7'))) {
                    char x = xnu(c);
                    ICONV_DECL(&x, 1);
                    assert(xe(xiu(x), c));
                    obuf = strg_sbuf, obufv = strg_sbuf + len;
                    olen = strg_slen, olenv = strg_slen - len;
                    ICONV_DO(cd, 0, {});
                    strg_sbuf = obuf, strg_slen = olen;    /* for later reuse */
                    len += (strg_slen - len - olenv);
                } else {
#else    /* !HAVE_ICONV */
                {
#endif    /* HAVE_ICONV */
                    if (len + cbyte > strg_slen)
                        MEM_RESIZE(strg_sbuf, strg_slen += BUFUNIT);
                    if (*w) {
                        if (LITTLE != ir_cur->f.little_endian)
                            CHGENDIAN(c, sizeof(c));
                        memcpy(strg_sbuf+len,
                               &c + ((ir_cur->f.little_endian)? 0: sizeof(c)-cbyte), cbyte);
                        len += cbyte;
                    } else
                        strg_sbuf[len++] = xnu(c);
                }
                clen++;
                s = e;
                continue;
            }
            break;    /* " or NUL */
        }
        if (n == t) {
            if (len + cbyte > strg_slen)
                MEM_RESIZE(strg_sbuf, strg_slen += BUFUNIT);
            memset(strg_sbuf+len, 0, cbyte);
            len += cbyte;
            clen++;
            break;
        }
        while ((n = n->next)->id != LEX_SCON)
            if (n->id < 0)
                strg_free((arena_t *)n->spell);
        ss = s = LEX_SPELL(n);
        if (*s == 'L')
            s++;
        e = ++s;    /* skips " */
    }

    if (len % cbyte != 0)
        err_dpos(clx_cpos, ERR_CONST_WIDENOTFIT);
    if (*w)
        clen = (len /= cbyte);

    if (clen - 1 > TL_STR_STD) {    /* -1 for NUL; note TL_STR_STD may warp around */
        err_dpos(clx_cpos, ERR_CONST_LONGSTR);
        err_dpos(clx_cpos, ERR_CONST_LONGSTRSTD, (unsigned long)TL_STR_STD);
    }

    return len;
}


#define N 0    /* no suffix */
#define U 1    /* suffix: U */
#define L 2    /* suffix: L */
#define X 3    /* suffix: UL */
#ifdef SUPPORT_LL
#define M 4    /* suffix: LL */
#define Z 5    /* suffix: ULL */
#endif    /* SUPPORT_LL */
#define D 0    /* base: decimal */
#define H 1    /* base: octal or hexadecimal */

/*
 *  determines the type of an integer constant
 */
static const char *icon(const char *cs, ux_t n, int ovf, int base, const lmap_t *pos)
{
    static struct tab {
        ux_t limit;
        ty_t *type;
#ifdef SUPPORT_LL
    } tab[Z+1][H+1][7];
#else    /* !SUPPORT_LL */
    } tab[X+1][H+1][5];
#endif    /* SUPPORT_LL */

    int suffix;
    struct tab *p;

    assert(cs);
    assert(pos);
    assert(ty_inttype);
#ifdef SUPPORT_LL
    assert(xgeu(xmxu, TG_ULLONG_MAX));
#else    /* !SUPPORT_LL */
    assert(xgeu(xmxu, TG_ULONG_MAX));
#endif    /* SUPPORT_LL */

    if (xe(tab[N][D][0].limit, xO)) {
        /* no suffix, decimal; different in C90 */
        tab[N][D][0].limit = TG_INT_MAX;
        tab[N][D][0].type  = ty_inttype;
        tab[N][D][1].limit = TG_LONG_MAX;
        tab[N][D][1].type  = ty_longtype;
#ifdef SUPPORT_LL
        tab[N][D][2].limit = TG_LLONG_MAX;
        tab[N][D][2].type  = ty_llongtype;
        tab[N][D][3].limit = TG_ULLONG_MAX;
        tab[N][D][3].type  = ty_ullongtype;
        tab[N][D][4].limit = xmxu;
        tab[N][D][4].type  = ty_inttype;
#else    /* SUPPORT_LL */
        tab[N][D][2].limit = TG_ULONG_MAX;
        tab[N][D][2].type  = ty_ulongtype;
        tab[N][D][3].limit = xmxu;
        tab[N][D][3].type  = ty_inttype;
#endif    /* SUPPORT_LL */

        /* no suffix, octal or hex */
        tab[N][H][0].limit = TG_INT_MAX;
        tab[N][H][0].type  = ty_inttype;
        tab[N][H][1].limit = TG_UINT_MAX;
        tab[N][H][1].type  = ty_unsignedtype;
        tab[N][H][2].limit = TG_LONG_MAX;
        tab[N][H][2].type  = ty_longtype;
        tab[N][H][3].limit = TG_ULONG_MAX;
        tab[N][H][3].type  = ty_ulongtype;
#ifdef SUPPORT_LL
        tab[N][H][4].limit = TG_LLONG_MAX;
        tab[N][H][4].type  = ty_llongtype;
        tab[N][H][5].limit = TG_ULLONG_MAX;
        tab[N][H][5].type  = ty_ullongtype;
        tab[N][H][6].limit = xmxu;
        tab[N][H][6].type  = ty_inttype;
#else    /* !SUPPORT_LL */
        tab[N][H][4].limit = xmxu;
        tab[N][H][4].type  = ty_inttype;
#endif    /* SUPPORT_LL */

        /* U, decimal, octal or hex */
        tab[U][H][0].limit = tab[U][D][0].limit = TG_UINT_MAX;
        tab[U][H][0].type  = tab[U][D][0].type  = ty_unsignedtype;
        tab[U][H][1].limit = tab[U][D][1].limit = TG_ULONG_MAX;
        tab[U][H][1].type  = tab[U][D][1].type  = ty_ulongtype;
#ifdef SUPPORT_LL
        tab[U][H][2].limit = tab[U][D][2].limit = TG_ULLONG_MAX;
        tab[U][H][2].type  = tab[U][D][2].type  = ty_ullongtype;
        tab[U][H][3].limit = tab[U][D][3].limit = xmxu;
        tab[U][H][3].type  = tab[U][D][3].type  = ty_inttype;
#else    /* !SUPPORT_LL */
        tab[U][H][2].limit = tab[U][D][2].limit = xmxu;
        tab[U][H][2].type  = tab[U][D][2].type  = ty_inttype;
#endif    /* SUPPORT_LL */

        /* L, decimal; different in C90 */
        tab[L][D][0].limit = TG_LONG_MAX;
        tab[L][D][0].type  = ty_longtype;
#ifdef SUPPORT_LL
        tab[L][D][1].limit = TG_LLONG_MAX;
        tab[L][D][1].type  = ty_llongtype;
        tab[L][D][2].limit = TG_ULLONG_MAX;
        tab[L][D][2].type  = ty_ullongtype;
        tab[L][D][3].limit = xmxu;
        tab[L][D][3].type  = ty_inttype;
#else    /* !SUPPORT_LL */
        tab[L][D][1].limit = TG_ULONG_MAX;
        tab[L][D][1].type  = ty_ulongtype;
        tab[L][D][2].limit = xmxu;
        tab[L][D][2].type  = ty_inttype;
#endif    /* SUPPORT_LL */

        /* L, octal or hex */
        tab[L][H][0].limit = TG_LONG_MAX;
        tab[L][H][0].type  = ty_longtype;
        tab[L][H][1].limit = TG_ULONG_MAX;
        tab[L][H][1].type  = ty_ulongtype;
#ifdef SUPPORT_LL
        tab[L][H][2].limit = TG_LLONG_MAX;
        tab[L][H][2].type  = ty_llongtype;
        tab[L][H][3].limit = TG_ULLONG_MAX;
        tab[L][H][3].type  = ty_ullongtype;
        tab[L][H][4].limit = xmxu;
        tab[L][H][4].type  = ty_inttype;
#else    /* !SUPPORT_LL */
        tab[L][H][2].limit = xmxu;
        tab[L][H][2].type  = ty_inttype;
#endif    /* SUPPORT_LL */

        /* UL, decimal, octal or hex */
        tab[X][H][0].limit = tab[X][D][0].limit = TG_ULONG_MAX;
        tab[X][H][0].type  = tab[X][D][0].type  = ty_ulongtype;
#ifdef SUPPORT_LL
        tab[X][H][1].limit = tab[X][D][1].limit = TG_ULLONG_MAX;
        tab[X][H][1].type  = tab[X][D][1].type  = ty_ullongtype;
        tab[X][H][2].limit = tab[X][D][2].limit = xmxu;
        tab[X][H][2].type  = tab[X][D][2].type  = ty_inttype;
#else    /* !SUPPORT_LL */
        tab[X][H][1].limit = tab[X][D][1].limit = xmxu;
        tab[X][H][1].type  = tab[X][D][1].type  = ty_inttype;
#endif    /* SUPPORT_LL */

#ifdef SUPPORT_LL
        /* LL, decimal, octal or hex */
        tab[M][H][0].limit = tab[M][D][0].limit = TG_LLONG_MAX;
        tab[M][H][0].type  = tab[M][D][0].type  = ty_llongtype;
        tab[M][H][1].limit = tab[M][D][1].limit = TG_ULLONG_MAX;
        tab[M][H][1].type  = tab[M][D][1].type  = ty_ullongtype;
        tab[M][H][2].limit = tab[M][D][2].limit = xmxu;
        tab[M][H][2].type  = tab[M][D][2].type  = ty_inttype;

        /* ULL, decimal, octal or hex */
        tab[Z][H][0].limit = tab[Z][D][0].limit = TG_ULLONG_MAX;
        tab[Z][H][0].type  = tab[Z][D][0].type  = ty_ullongtype;
        tab[Z][H][1].limit = tab[Z][D][1].limit = xmxu;
        tab[Z][H][1].type  = tab[Z][D][1].type  = ty_inttype;
#endif    /* SUPPORT_LL */
    }

    base = (base == 10)? D: H;
    suffix = N;

    if (tolower((unsigned char)cs[0]) == 'l') {
#ifdef SUPPORT_LL
        if (cs[1] == cs[0])
            cs += 2, suffix = M;
        else
#endif    /* SUPPORT_LL */
            cs++, suffix = L;
    }
    if (tolower((unsigned char)cs[0]) == 'u')
        cs++, suffix++;
    if (suffix <= U && tolower((unsigned char)cs[0]) == 'l') {
#ifdef SUPPORT_LL
        if (cs[1] == cs[0])
            cs += 2, suffix += M;
        else
#endif    /* SUPPORT_LL */
            cs++, suffix += L;
    }

    for (p = tab[suffix][base]; xgu(n, p->limit); p++)
        continue;
    if (ovf || (xe(p->limit, xmxu) && p->type == ty_inttype)) {
        err_dpos(pos, ERR_CONST_LARGEINT);
#ifdef SUPPORT_LL
        n = TG_ULLONG_MAX;
        tval.type = ty_ullongtype;
#else    /* !SUPPORT_LL */
        n = TG_ULONG_MAX;
        tval.type = ty_ulongtype;
#endif    /* SUPPORT_LL */
    } else
        tval.type = p->type;

#ifdef SUPPORT_LL
    if (suffix % 2 == 0 && base == D && TY_ISUNSIGN(p->type))
        err_dpos(pos, ERR_CONST_LARGEUNSIGN);
    else if (tval.type == ty_llongtype && (suffix == N || suffix == L) && xleu(n, TG_ULONG_MAX)) {
        err_dpos(pos, ERR_CONST_UNSIGNINC90);
        if (main_opt()->std == 1)
            tval.type = ty_ulongtype;
    }
    if ((TY_ISLLONG(tval.type) || TY_ISULLONG(tval.type)))
        err_dpos(pos, ERR_CONST_LLONGINC90, tval.type);
#endif    /* SUPPORT_LL */

#ifdef SUPPORT_LL
    if (tval.type->op == TY_INT || tval.type->op == TY_LONG || tval.type->op == TY_LLONG)
#else    /* !SUPPORT_LL */
    if (tval.type->op == TY_INT || tval.type->op == TY_LONG)
#endif    /* SUPPORT_LL */
        tval.u.c.v.s = n;
    else
        tval.u.c.v.u = n;

    return cs;
}

#undef H
#undef D
#undef Z
#undef M
#undef X
#undef L
#undef U
#undef N


/*
 *  determines the type of a floating constant;
 *  ASSUMPTION: fp types of the host are same as those of the target
 */
static const char *fcon(const char *cs, long double ld, const lmap_t *pos)
{
    assert(cs);
    assert(pos);
    assert(ty_floattype);    /* ensures types initiailized */

    switch(*cs) {
        case 'f':
        case 'F':
            cs++;    /* skips f or F */
            if ((OVF(ld) && errno == ERANGE) || ld > TG_FLT_MAX) {
                err_dpos(pos, ERR_CONST_LARGEFP);
                ld = TG_FLT_MAX;
            } else if ((ld == 0.0 && errno == ERANGE) || (ld > 0.0 && ld < TG_FLT_MIN)) {
                err_dpos(pos, ERR_CONST_TRUNCFP);
                ld = 0.0f;
            }
            tval.type = ty_floattype;
            tval.u.c.v.f = (float)ld;
            break;
        case 'l':
        case 'L':
            cs++;    /* skips l or L */
            if ((OVF(ld) && errno == ERANGE) || ld > TG_LDBL_MAX) {
                err_dpos(pos, ERR_CONST_LARGEFP);
                ld = TG_LDBL_MAX;
            } else if ((ld == 0.0 && errno == ERANGE) || (ld > 0.0 && ld < TG_LDBL_MIN))
                err_dpos(pos, ERR_CONST_TRUNCFP);
            tval.type = ty_ldoubletype;
            tval.u.c.v.ld = (long double)ld;
            break;
        default:
            if ((OVF(ld) && errno == ERANGE) || ld > TG_DBL_MAX) {
                err_dpos(pos, ERR_CONST_LARGEFP);
                ld = (double)TG_DBL_MAX;
            } else if ((ld == 0.0 && errno == ERANGE) || (ld > 0.0 && ld < TG_DBL_MIN)) {
                err_dpos(pos, ERR_CONST_TRUNCFP);
                ld = 0.0;
            }
            tval.type = ty_doubletype;
            tval.u.c.v.d = (double)ld;
            break;
    }

    return cs;
}


/*
 *  recognizes integer or floating constants;
 *  ASSUMPTION: strtold() supported on the host
 */
static int ifcon(lex_t *t)
{
    ux_t n;
    int b, d;
    long double ld;
    int err = 0, ovf = 0;
    const char *ss, *s;
    char *p = "0123456789abcdef";    /* no const for reuse with strtold() */

    assert(t);

    ss = s = LEX_SPELL(t);

    if (*s == '.')
        goto fcon;
    n = xO;
    if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') &&
        isxdigit(((unsigned char *)s)[2])) {    /* 0x[0-9] */
        b = 16;
        s++;    /* skips 0 */
        while (isxdigit(*(unsigned char *)++s)) {
            d = strchr(p, tolower(*(unsigned char *)s)) - p;
            if (xt(xba(n, xbc(xsrl(xmxu, 4)))))
                ovf = 1;
            n = xau(xsl(n, 4), xiu(d));
        }
        s = icon(s, n, ovf, b, t->pos);
        b = LEX_ICON;
    } else {    /* 0 or other digits */
        b = (*s == '0')? 8: 10;
        if (b == 8)
            while (isdigit(*(unsigned char *)s)) {
                d = *s++ - '0';
                if (*s == '8' || *s == '9')
                    p = (char *)s, err = 1;
                if (xt(xba(n, xbc(xsrl(xmxu, 3)))))
                    ovf = 1;
                n = xau(xsl(n, 3), xiu(d));
            }
        else    /* b == 10 */
            while (isdigit(*(unsigned char *)s)) {
                d = *s++ - '0';
                if (xgu(n, xdu(xsu(xmxu, xiu(d)), xiu(10))))
                    ovf = 1;
                n = xau(xmu(xiu(10), n), xiu(d));
            }

        fcon:
            if (b != 16 && (*s == '.' || *s == 'e' || *s == 'E')) {
                if (*s == '.')
                    do {
                        s++;    /* skips . and digits */
                    } while(isdigit(*s));
                if (*s == 'e' || *s == 'E') {
                    if (*++s == '-' || *s == '+')    /* skips e or E */
                        s++;    /* skips - or + */
                    if (!isdigit(*s)) {
                        err_dpos(lmap_spell(t, ss, s, s+1), ERR_CONST_NOEXPDIG);
                        err = 1;
                    }
                }
                if (!err) {
                    errno = 0;
                    ld = strtold(ss, &p);
                    s = fcon((s = p), ld, t->pos);
                }
                b = LEX_FCON;
            } else {
                if (err)
                    err_dpos(lmap_spell(t, ss, p, p+1), ERR_CONST_ILLOCTESC);
                else
                    s = icon(s, n, ovf, b, t->pos);
                b = LEX_ICON;
            }
    }

    if (*s && !err) {
        for (p = (char *)s; *p; p++)
            continue;
        err_dpos(lmap_spell(t, ss, s, p), ERR_CONST_PPNUMSFX, s, b);
        err = 1;
    }

    clx_sym = (err)? NULL: &tval;
    return b;
}
Exemple #16
0
/**
 * Get the color from reflection and refraction for transparent objects.
 *
 * @param ray the viewing ray
 * @param hit_rec the hit record for the point being colored.
 * @param depth the current ray-tracing recursion depth.
 * @param in_trans whether the ray is inside a transparent surface or not.
 *
 * @return the color to add from transparency of ray.
 */
color_t get_transparency(ray3_t* ray, hit_record_t* hit_rec, int depth, bool
        in_trans) {
    //debug("get_transparency");

    // Use notation from Shirley and Marschner:
    // d - ray
    // n - normal = closest_hit_rec->normal
    // <i>n></i> - refractive index
    // t - transformed ray direction

    // Calculate reflected ray refl_ray: r = reflect(d,n).
    vector3_t normal = hit_rec->normal;
    vector3_t refl_vector;
    reflect(ray, &normal, &refl_vector);
    normalize(&refl_vector);
    ray3_t refl_ray = { hit_rec->hit_pt, refl_vector };

    // Store locally for cleaner code.
    surface_t* sfc = hit_rec->sfc;
    float index = sfc->refr_index;

    // Variables populated in if/else blocks:
    color_t trans_color;
    color_t k;
    float c;
    vector3_t t_vec;

    // Normalize ray_dir for dot product
    vector3_t ray_dir = ray->dir;
    normalize(&ray_dir);
    if (dot(&ray_dir, &normal) < 0) {
        // Calculate direction refracted (transformed) ray, t_vec; 
        refract(ray, &normal, index, &t_vec, in_trans);
        c = ( -1.0f * dot(&ray_dir, &normal));
        k = (color_t) {1.0f, 1.0f, 1.0f};
    } else {

        // Intensity of light diminishes by the attenuation constant of the
        // surface proportionally to the distance the ray of light travels
        // through the surface. To calculate this distance that the ray of
        // light spends in the surface we follow a procedure similar to the
        // procedure of shadows. We Iterate through all surfaces looking for
        // the closest hit object in the direction of the refracted ray. Then
        // we take the distance between the first hit records hit_pt and the
        // closest hit record's hit_pt which is on the closest object.

        vector3_t dist_vec;
        refract(ray, &normal, index, &dist_vec, in_trans);
        ray3_t t_ray = {hit_rec->hit_pt, dist_vec};
        hit_record_t t_hit_rec, t_closest_hit_rec;

        // Get a hit record for the closest object that is hit in dir t_ray.
        bool hit_something = false;
        float t1 = FLT_MAX;
        list356_itr_t* s = lst_iterator(surfaces);
        while (lst_has_next(s)) {
            surface_t* sfc = lst_next(s);
            if (sfc_hit(sfc, &t_ray, EPSILON, t1, &t_hit_rec)) {
                if (t_hit_rec.t < t1) {
                    hit_something = true;
                    memcpy(&t_closest_hit_rec, &t_hit_rec, 
                            sizeof(hit_record_t));
                    t1 = t_hit_rec.t;
                }
            }
        }
        lst_iterator_free(s);
        float t = dist(&hit_rec->hit_pt, &t_closest_hit_rec.hit_pt);

        // Calculate attenuation.
        color_t* a = sfc->atten;
        k = (color_t) {
            exp(-1.0f * (a->red) * t),
            exp(-1.0f * (a->green) * t),
            exp(-1.0f * (a->blue) * t) };

        vector3_t neg_normal; // neg_normal = -n
        multiply(&normal, -1.0f, &neg_normal);
        // inv_index = 1/n = 1/refr_index
        float inv_index = 1.0f/index;
        if (refract(ray, &neg_normal, inv_index, &t_vec, in_trans)) {
            c = dot(&t_vec, &normal);
        } else {
            trans_color = ray_trace(refl_ray, EPSILON, FLT_MAX, depth-1,
                    !in_trans);
            trans_color.red = trans_color.red*k.red;
            trans_color.green = trans_color.green*k.green;
            trans_color.blue = trans_color.blue*k.blue;
            //return (color_t) {1.0f, 1.0f, 0.0f};
            return trans_color;
        }
    }

    float R0 = (( (index - 1)*(index - 1) )/( (index + 1)*(index + 1) ));
    float R = (R0 + (1 - R0)*((1 - c)*(1 - c)*(1 - c)*(1 - c)*(1 - c)));
    color_t trans_color1, trans_color2;

    // Recursively ray trace on the reflected ray and the refracted ray.
    trans_color1 = ray_trace(refl_ray, EPSILON, FLT_MAX, depth-1, !in_trans);
    ray3_t t_ray = {hit_rec->hit_pt, t_vec};
    trans_color2 = ray_trace(t_ray, EPSILON, FLT_MAX, depth-1, !in_trans);

    // Combine the reflected and refracted ray and return.
    trans_color.red = k.red*( (R*trans_color1.red) + ((1.0f -
                    R)*trans_color2.red));
    trans_color.green = k.green*( (R*trans_color1.green) + ((1.0f -
                    R)*trans_color2.green));
    trans_color.blue = k.blue*( (R*trans_color1.blue) + ((1.0f -
                    R)*trans_color2.blue));
    return trans_color;
}
Exemple #17
0
/*
 *  ======== add_to_free_list ========
 *  Purpose:
 *      Coelesce node into the freelist in ascending size order.
 */
static void add_to_free_list(struct cmm_allocator *allocator,
			     struct cmm_mnode *pnode)
{
	struct cmm_mnode *node_prev = NULL;
	struct cmm_mnode *node_next = NULL;
	struct cmm_mnode *mnode_obj;
	u32 dw_this_pa;
	u32 dw_next_pa;

	DBC_REQUIRE(pnode != NULL);
	DBC_REQUIRE(allocator != NULL);
	dw_this_pa = pnode->dw_pa;
	dw_next_pa = NEXT_PA(pnode);
	mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
	while (mnode_obj) {
		if (dw_this_pa == NEXT_PA(mnode_obj)) {
			/* found the block ahead of this one */
			node_prev = mnode_obj;
		} else if (dw_next_pa == mnode_obj->dw_pa) {
			node_next = mnode_obj;
		}
		if ((node_prev == NULL) || (node_next == NULL)) {
			/* next node. */
			mnode_obj = (struct cmm_mnode *)
			    lst_next(allocator->free_list_head,
				     (struct list_head *)mnode_obj);
		} else {
			/* got 'em */
			break;
		}
	}			/* while */
	if (node_prev != NULL) {
		/* combine with previous block */
		lst_remove_elem(allocator->free_list_head,
				(struct list_head *)node_prev);
		/* grow node to hold both */
		pnode->ul_size += node_prev->ul_size;
		pnode->dw_pa = node_prev->dw_pa;
		pnode->dw_va = node_prev->dw_va;
		/* place node on mgr nodeFreeList */
		delete_node((struct cmm_object *)allocator->hcmm_mgr,
			    node_prev);
	}
	if (node_next != NULL) {
		/* combine with next block */
		lst_remove_elem(allocator->free_list_head,
				(struct list_head *)node_next);
		/* grow da node */
		pnode->ul_size += node_next->ul_size;
		/* place node on mgr nodeFreeList */
		delete_node((struct cmm_object *)allocator->hcmm_mgr,
			    node_next);
	}
	/* Now, let's add to freelist in increasing size order */
	mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
	while (mnode_obj) {
		if (pnode->ul_size <= mnode_obj->ul_size)
			break;

		/* next node. */
		mnode_obj =
		    (struct cmm_mnode *)lst_next(allocator->free_list_head,
						 (struct list_head *)mnode_obj);
	}
	/* if mnode_obj is NULL then add our pnode to the end of the freelist */
	if (mnode_obj == NULL) {
		lst_put_tail(allocator->free_list_head,
			     (struct list_head *)pnode);
	} else {
		/* insert our node before the current traversed node */
		lst_insert_before(allocator->free_list_head,
				  (struct list_head *)pnode,
				  (struct list_head *)mnode_obj);
	}
}
Exemple #18
0
/*
 *  ======== rmm_alloc ========
 */
int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
		     u32 align, u32 *dsp_address, bool reserve)
{
	struct rmm_ovly_sect *sect;
	struct rmm_ovly_sect *prev_sect = NULL;
	struct rmm_ovly_sect *new_sect;
	u32 addr;
	int status = 0;

	DBC_REQUIRE(target);
	DBC_REQUIRE(dsp_address != NULL);
	DBC_REQUIRE(size > 0);
	DBC_REQUIRE(reserve || (target->num_segs > 0));
	DBC_REQUIRE(refs > 0);

	if (!reserve) {
		if (!alloc_block(target, segid, size, align, dsp_address)) {
			status = -ENOMEM;
		} else {
			/* Increment the number of allocated blocks in this
			 * segment */
			target->seg_tab[segid].number++;
		}
		goto func_end;
	}
	/* An overlay section - See if block is already in use. If not,
	 * insert into the list in ascending address size. */
	addr = *dsp_address;
	sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list);
	/*  Find place to insert new list element. List is sorted from
	 *  smallest to largest address. */
	while (sect != NULL) {
		if (addr <= sect->addr) {
			/* Check for overlap with sect */
			if ((addr + size > sect->addr) || (prev_sect &&
							   (prev_sect->addr +
							    prev_sect->size >
							    addr))) {
				status = -ENXIO;
			}
			break;
		}
		prev_sect = sect;
		sect = (struct rmm_ovly_sect *)lst_next(target->ovly_list,
							(struct list_head *)
							sect);
	}
	if (!status) {
		/* No overlap - allocate list element for new section. */
		new_sect = kzalloc(sizeof(struct rmm_ovly_sect), GFP_KERNEL);
		if (new_sect == NULL) {
			status = -ENOMEM;
		} else {
			lst_init_elem((struct list_head *)new_sect);
			new_sect->addr = addr;
			new_sect->size = size;
			new_sect->page = segid;
			if (sect == NULL) {
				/* Put new section at the end of the list */
				lst_put_tail(target->ovly_list,
					     (struct list_head *)new_sect);
			} else {
				/* Put new section just before sect */
				lst_insert_before(target->ovly_list,
						  (struct list_head *)new_sect,
						  (struct list_head *)sect);
			}
		}
	}
func_end:
	return status;
}
Exemple #19
0
/** Get the shade determined by a given ray.
 *  
 *  @param ray the ray to trace.
 *  @param t0 the start of the interval for which to get a shade.
 *  @param t1 the end of the interval for which to get a shade.
 *  @param depth the maximum number of times a reflect ray will be
 *      cast for objects with non-NULL reflective color.
 *
 *  @return the color corresponding to the closest object hit by
 *      <code>r</code> in the interval <code>[t0, t1]</code>.
 */
color_t ray_trace(ray3_t ray, float t0, float t1, int depth) {
    assert(depth >= 0) ;

    color_t color = {0.0, 0.0, 0.0} ;

    if (depth ==0) return color ;

    hit_record_t hit_rec, closest_hit_rec ;

    // Get a hit record for the closest object that is hit.
    bool hit_something = false ;
    list356_itr_t* s = lst_iterator(surfaces) ;
    while (lst_has_next(s)) {
        surface_t* sfc = lst_next(s) ;
        if (sfc_hit(sfc, &ray, t0, t1, &hit_rec)) {
            if (hit_rec.t < t1) {
                hit_something = true ;
                memcpy(&closest_hit_rec, &hit_rec, 
                        sizeof(hit_record_t)) ;
                t1 = hit_rec.t ;
            }
        }
    }
    lst_iterator_free(s) ;

    // If we hit something, color the pixel.
    if (hit_something) {
        surface_t* sfc = closest_hit_rec.sfc ;

        // Specular reflection.
        if (sfc->refl_color != NULL) {
            color_t refl_color = get_specular_refl(&ray,
                    &closest_hit_rec, depth) ;
            add_scaled_color(&color, sfc->refl_color, &refl_color, 1.0f) ;
        }

        // Ambient shading.
        add_scaled_color(&color, sfc->ambient_color, &ambient_light, 1.0f) ;

        // Lighting.
        list356_itr_t* light_itr = lst_iterator(lights) ;
        while (lst_has_next(light_itr)) {
            light_t* light = lst_next(light_itr) ;
            vector3_t light_dir ;
            pv_subtract(light->position, &(closest_hit_rec.hit_pt), 
                    &light_dir) ;
            normalize(&light_dir) ;

            // Check for global shadows.
            bool do_lighting = true ;
            ray3_t light_ray = {closest_hit_rec.hit_pt, light_dir} ;
            float light_dist = dist(&closest_hit_rec.hit_pt,
                    light->position) ;
            s = lst_iterator(surfaces) ;
            while (lst_has_next(s)) {
                surface_t* sfc = lst_next(s) ;
                if (sfc_hit(sfc, &light_ray, EPSILON, light_dist, &hit_rec)) {
                    do_lighting = false ;
                    break ;
                }
            }
            lst_iterator_free(s) ;
            if (!do_lighting) {
                continue ;
            }

            // Lambertian shading.
            float scale = get_lambert_scale(&light_dir, &closest_hit_rec) ;
            add_scaled_color(&color, sfc->diffuse_color, light->color, scale) ;

            // Blin-Phong shading.
            float phong_scale = get_blinn_phong_scale(&ray, &light_dir,
                    &closest_hit_rec) ;
            add_scaled_color(&color, sfc->spec_color, light->color, 
                    phong_scale) ;
        }   // while(lst_has_next(light_itr))

        lst_iterator_free(light_itr) ;

    }   // if (hit_something)

    return color ;
}