Example #1
0
*/ RL_API REBYTE *RL_Word_String(u32 word)
/*
**	Return a string related to a given global word identifier.
**
**	Returns:
**		A copy of the word string, null terminated.
**	Arguments:
**		word - a global word identifier
**	Notes:
**		The result is a null terminated copy of the name for your own use.
**		The string is always UTF-8 encoded (chars > 127 are encoded.)
**		In this API, word identifiers are always canonical. Therefore,
**		the returned string may have different spelling/casing than expected.
**		The string is allocated with OS_ALLOC and you can OS_FREE it any time.
**
***********************************************************************/
{
	REBYTE *s1, *s2;
	// !!This code should use a function from c-words.c (but nothing perfect yet.)
	if (word == 0 || word >= PG_Word_Table.series->tail) return 0;
	s1 = VAL_SYM_NAME(BLK_SKIP(PG_Word_Table.series, word));
	s2 = OS_ALLOC_ARRAY(REBYTE, LEN_BYTES(s1) + 1);
	COPY_BYTES(s2, s1, LEN_BYTES(s1) + 1);
	return s2;
}
Example #2
0
//
//  RL_Word_String: C
// 
// Return a string related to a given global word identifier.
// 
// Returns:
//     A copy of the word string, null terminated.
// Arguments:
//     word - a global word identifier
// Notes:
//     The result is a null terminated copy of the name for your own use.
//     The string is always UTF-8 encoded (chars > 127 are encoded.)
//     In this API, word identifiers are always canonical. Therefore,
//     the returned string may have different spelling/casing than expected.
//     The string is allocated with OS_ALLOC and you can OS_FREE it any time.
//
RL_API REBYTE *RL_Word_String(u32 word)
{
    REBYTE *s1, *s2;
    // !!This code should use a function from c-words.c (but nothing perfect yet.)
    if (word == 0 || word >= ARR_LEN(PG_Word_Table.array)) return 0;
    s1 = VAL_SYM_NAME(ARR_AT(PG_Word_Table.array, word));
    s2 = OS_ALLOC_N(REBYTE, LEN_BYTES(s1) + 1);
    COPY_BYTES(s2, s1, LEN_BYTES(s1) + 1);
    return s2;
}
Example #3
0
static REBYTE *Get_Next_Line()
{
	REBYTE *bp = inbuf;
	REBYTE *out;
	REBCNT len;

	// Scan for line terminator or end:
	for (bp = inbuf; *bp != CR && *bp != LF && *bp != 0; bp++);

	// If found, copy the line and remove it from buffer:
	if (*bp) {
		if (*bp == CR && bp[1] == LF) bp++;
		len = bp - inbuf;
		out = OS_ALLOC_ARRAY(REBYTE, len + 2);
		COPY_BYTES(out, inbuf, len+1);
		out[len+1] = 0;
		memmove(inbuf, bp + 1, 1 + LEN_BYTES(bp + 1));
		return out;
	}

	return 0; // more input needed
}
Example #4
0
*/	static int Read_Directory(REBREQ *dir, REBREQ *file)
/*
**		This function will read a file directory, one file entry
**		at a time, then close when no more files are found.
**
**	Procedure:
**
**		This function is passed directory and file arguments.
**		The dir arg provides information about the directory to read.
**		The file arg is used to return specific file information.
**
**		To begin, this function is called with a dir->handle that
**		is set to zero and a dir->file.path string for the directory.
**
**		The directory is opened and a handle is stored in the dir
**		structure for use on subsequent calls. If an error occurred,
**		dir->error is set to the error code and -1 is returned.
**		The dir->size field can be set to the number of files in the
**		dir, if it is known. The dir->file.index field can be used by this
**		function to store information between calls.
**
**		If the open succeeded, then information about the first file
**		is stored in the file argument and the function returns 0.
**		On an error, the dir->error is set, the dir is closed,
**		dir->handle is nulled, and -1 is returned.
**
**		The caller loops until all files have been obtained. This
**		action should be uninterrupted. (The caller should not perform
**		additional OS or IO operations between calls.)
**
**		When no more files are found, the dir is closed, dir->handle
**		is nulled, and 1 is returned. No file info is returned.
**		(That is, this function is called one extra time. This helps
**		for OSes that may deallocate file strings on dir close.)
**
**		Note that the dir->file.path can contain wildcards * and ?. The
**		processing of these can be done in the OS (if supported) or
**		by a separate filter operation during the read.
**
**		Store file date info in file->file.index or other fields?
**		Store permissions? Ownership? Groups? Or, require that
**		to be part of a separate request?
**
***********************************************************************/
{
	struct stat info;
	struct dirent *d;
	char *cp;
	DIR *h;
	int n;

	// Remove * from tail, if present. (Allowed because the
	// path was copied into to-local-path first).
	n = strlen(cp = dir->file.path);
	if (n > 0 && cp[n-1] == '*') cp[n-1] = 0;

	// If no dir handle, open the dir:
	if (!(h = dir->handle)) {
		h = opendir(dir->file.path);
		if (!h) {
			dir->error = errno;
			return DR_ERROR;
		}
		dir->handle = h;
		CLR_FLAG(dir->flags, RRF_DONE);
	}

	// Get dir entry (skip over the . and .. dir cases):
	do {
		// Read next file entry or error:
		if (!(d = readdir(h))) {
			//dir->error = errno;
			closedir(h);
			dir->handle = 0;
			//if (dir->error) return DR_ERROR;
			SET_FLAG(dir->flags, RRF_DONE); // no more files
			return DR_DONE;
		}
		cp = d->d_name;
	} while (cp[0] == '.' && (cp[1] == 0 || cp[1] == '.'));

	file->modes = 0;
	COPY_BYTES(file->file.path, cp, MAX_FILE_NAME);

	// NOTE: not all posix filesystems support this (mainly
	// the Linux and BSD support it.) If this fails to build, a
	// different mechanism must be used. However, this is the
	// most efficient, because it does not require a separate
	// file system call for determining directories.
	if (d->d_type == DT_DIR) SET_FLAG(file->modes, RFM_DIR);

	// Line below DOES NOT WORK -- because we need full path.
	//Get_File_Info(file); // updates modes, size, time

	return DR_DONE;
}
Example #5
0
KS_E_ERROR ks_file_write(KS_FILE_PTR file_ptr,
                         LongWord position,
                         LongWord data_size,
                         Pointer data_buffer)
{
    /* ************************************************************** *
     *  Local declarations:                                           *
     * ************************************************************** */

    KS_E_ERROR   error;            /* Holds error codes for subroutine*/
                                   /*  calls                          */
    LongWord     data_offset;      /* Offset into the buffer to return*/
    LongWord     remaining_space;  /* Space remaining in file buffer  */
    LongWord     buffer_request;   /* Size of each copy from the      */
                                   /*  file buffer                    */


    ROUTINE_ENTER();


    /* ************************************************************** *
     *  Verify the structure ID passed in is the correct one.         *
     * ************************************************************** */

    if (file_ptr->struct_id != KS_FILE_ID)
        {
        KS_ERROR(KS_E_INVALID_STRUCT_ID, KS_FILE_ID);
        };


    /* ************************************************************** *
     *  Zero the number of bytes transfered in the KS_FILE structure. *
     * ************************************************************** */

    file_ptr->data_size = 0;


    /* ************************************************************** *
     *  If there is a buffer, then lets put data into the file buffer.*
     * ************************************************************** */

    if (file_ptr->buffer_size != NULL)
        {

        /* ********************************************************** *
         *  Loop till we satisfy the request (or take an error)       *
         * ********************************************************** */

        data_offset = 0;

        while (data_size > 0)
            {

            /* ****************************************************** *
             *  Calculate the remaining space in the buffer.  If      *
             *  there is any space left in the buffer then lets copy  *
             *  as much as we need to into the file buffer.           *
             * ****************************************************** */

            remaining_space = (file_ptr->buffer_available) -
                              (file_ptr->buffer_offset);

            if (remaining_space > 0)
                {
                buffer_request = MIN(data_size,
                                     remaining_space);

                COPY_BYTES(data_buffer,
                           data_offset,
                           file_ptr->buffer,
                           file_ptr->buffer_offset,
                           buffer_request);

                /* ************************************************** *
                 *  Now modify the parameters of the buffers by:      *
                 *                                                    *
                 *  1) Adding the size of the request to the file     *
                 *  buffer ofset and the data offset (IE: Indices to  *
                 *  the file buffer and the read request buffer).     *
                 *                                                    *
                 *  2) Subtracting the request size from the read     *
                 *  request size and the remaining number of          *
                 *  characters in the file buffer.                    *
                 * ************************************************** */

                file_ptr->buffer_offset = file_ptr->buffer_offset +
                                          buffer_request;

                data_offset = data_offset + buffer_request;

                file_ptr->data_size = data_offset; 

                data_size = data_size - buffer_request;

                remaining_space = remaining_space - buffer_request;
                };


            /* ****************************************************** *
             *  If the file buffer is full, then we have to write it  *
             *  to disk.  The problem is that the buffer size may     *
             *  have changed due to what our user wants (users are    *
             *  bound to be the end of all computing...).  This means *
             *  that we'll junp through a few hoops if we must change *
             *  buffer sizes - so expect some weirdness here.         *
             * ****************************************************** */

            if (remaining_space == 0)
                {

                /* ************************************************** *
                 *  Issue a Read to the file into our buffer.         *
                 * ************************************************** */

                KSf_pkts.IO.pCount = 4;
                KSf_pkts.IO.refNum = file_ptr->refNum;
                KSf_pkts.IO.dataBuffer = TO_POINTER(file_ptr->buffer);
                KSf_pkts.IO.requestCount = file_ptr->buffer_size;

                WriteGS(&KSf_pkts.IO);

                if ((error = GET_ERROR()) != KS_E_SUCCESS)
                    {
                    goto EXIT_NOW;
                    };

                file_ptr->buffer_available = file_ptr->buffer_size;
                file_ptr->buffer_offset = 0;


                /* ************************************************** *
                 *  This is the above mentioned weirdness - if the    *
                 *  user specified a different size buffer we will    *
                 *  no comply with their wishes.                      *
                 * ************************************************** */

                if (file_ptr->buffer_size != KSf_FileBufferSize)
                    {
                    KS_MEMORY_DEALLOCATE(file_ptr->buffer_handle,
                                         error);

                    if (error != KS_E_SUCCESS)
                        {
                        goto EXIT_NOW;
                        };

                    KS_MEMORY_ALLOCATE(attrFixed + attrLocked,
                                       KSf_FileBufferSize,
                                       BUFFER_USERID,
                                       file_ptr->buffer_handle,
                                       error);

                    if (error != KS_E_SUCCESS)
                        {
                        goto EXIT_NOW;
                        };

                    file_ptr->buffer = (Byte *)
                                         *(file_ptr->buffer_handle);

                    file_ptr->buffer_size = KSf_FileBufferSize;

                    file_ptr->buffer_available = KSf_FileBufferSize;
                    };

                };  /* End if there is no remaining buffer space      */

            };  /* End while there are characters to be read...       */

        KS_SUCCESS();

        };  /* End if we are doing buffer I/O from the file           */




    /* ************************************************************** *
     *  Ok, we've done enough buffering... lets do some real output...*
     *                                                                *
     *  Position the 'mark' (where we will write to) in the file.     *
     *  Note: We'll move the mark only if our user asks us to.        *
     * ************************************************************** */

    if (position != KS_NEXT_FILE_POSITION)
        {
        KSf_pkts.position.pCount = 3;
        KSf_pkts.position.refNum = file_ptr->refNum;
        KSf_pkts.position.base = startPlus;
        KSf_pkts.position.displacement = position;

        SetMarkGS(&KSf_pkts.position);

        if ((error = GET_ERROR()) != KS_E_SUCCESS)
            {
            goto EXIT_NOW;
            };

        };  /* End if we must change the file position                */


    /* ************************************************************** *
     *  Setup the I/O packet and write what our user is asking for.   *
     * ************************************************************** */

    KSf_pkts.IO.pCount = 4;
    KSf_pkts.IO.refNum = file_ptr->refNum;
    KSf_pkts.IO.dataBuffer = data_buffer;
    KSf_pkts.IO.requestCount = data_size;

    WriteGS(&KSf_pkts.IO);

    if ((error = GET_ERROR()) != KS_E_SUCCESS)
        {
        goto EXIT_NOW;
        };


    /* ************************************************************** *
     *  Save the number of bytes transfered in the KS_FILE structure. *
     * ************************************************************** */

    file_ptr->data_size = KSf_pkts.IO.transferCount;


    /* ************************************************************** *
     *  Return the status back to our caller.                         *
     * ************************************************************** */

EXIT_NOW:

    if (error != KS_E_SUCCESS)
        {
        KS_ERROR(error, KS_FILE_ID);
        };

    KS_SUCCESS();

}   /* End of ks_file_write()                                         */
Example #6
0
*/	void Crash(REBINT id, ...)
/*
**		Print a failure message and abort.
**
**		LATIN1 ONLY!! (For now)
**
**		The error is identified by id number, which can reference an
**		error message string in the boot strings block.
**
**		Note that lower level error messages should not attempt to
**		use the %r (mold value) format (uses higher level functions).
**
**		See panics.h for list of crash errors.
**
***********************************************************************/
{
	va_list args;
	REBYTE buf[CRASH_BUF_SIZE];
	REBYTE *msg;
	REBINT n = 0;

	va_start(args, id);

	DISABLE_GC;
	if (Reb_Opts->crash_dump) {
		Dump_Info();
		Dump_Stack(0, 0);
	}

	// "REBOL PANIC #nnn:"
	COPY_BYTES(buf, Crash_Msgs[CM_ERROR], CRASH_BUF_SIZE);
	APPEND_BYTES(buf, " #", CRASH_BUF_SIZE);
	Form_Int(buf + LEN_BYTES(buf), id);
	APPEND_BYTES(buf, ": ", CRASH_BUF_SIZE);

	// "REBOL PANIC #nnn: put error message here"
	// The first few error types only print general error message.
	// Those errors > RP_STR_BASE have specific error messages (from boot.r).
	if      (id < RP_BOOT_DATA) n = CM_DEBUG;
	else if (id < RP_INTERNAL) n = CM_BOOT;
	else if (id < RP_ASSERTS)  n = CM_INTERNAL;
	else if (id < RP_DATATYPE) n = CM_ASSERT;
	else if (id < RP_STR_BASE) n = CM_DATATYPE;
	else if (id > RP_STR_BASE + RS_MAX - RS_ERROR) n = CM_DEBUG;

	// Use the above string or the boot string for the error (in boot.r):
	msg = (REBYTE*)(n >= 0 ? Crash_Msgs[n] : BOOT_STR(RS_ERROR, id - RP_STR_BASE - 1));
	Form_Var_Args(buf + LEN_BYTES(buf), CRASH_BUF_SIZE - 1 - LEN_BYTES(buf), msg, args);

	n = LEN_BYTES(Crash_Msgs[CM_CONTACT]);
	if ((LEN_BYTES(buf) + n) < (CRASH_BUF_SIZE - 1))
		APPEND_BYTES(buf, Crash_Msgs[CM_CONTACT], n);

	// Convert to OS-specific char-type:
#ifdef disable_for_now //OS_WIDE_CHAR   /// win98 does not support it
	{
		REBCHR s1[512];
		REBCHR s2[2000];

		n = TO_OS_STR(s1, Crash_Msgs[CM_ERROR], LEN_BYTES(Crash_Msgs[CM_ERROR]));
		if (n > 0) s1[n] = 0; // terminate
		else OS_EXIT(200); // bad conversion

		n = TO_OS_STR(s2, buf, LEN_BYTES(buf));
		if (n > 0) s2[n] = 0;
		else OS_EXIT(200);

		OS_CRASH(s1, s2);
	}
#else
	OS_CRASH(Crash_Msgs[CM_ERROR], buf);
#endif
}