Patch attached implements an embedding interface for Parrot and re-writes test_main.c to use it. It also rewrites the switch handling stuff into something that looks decent and adds -h (help) and -v (version) switches.
I'd like to emphasize that this interface is preliminary. Several functions are missing, and at least one function is temporary. Still, this'll probably be enough to be usable. Unfortunately, I will probably not be able to apply this myself. In the course of making the patch, I accidentally did a 'make distclean' instead of 'make cvsclean', and I *still* don't have a usable patch program, so I'll probably have to resync from the original and lose all my changes, plus my work-in-progress on jsr and friends. Ugh. --Brent Dax [EMAIL PROTECTED] Parrot Configure pumpking and regex hacker Check out the Parrot FAQ: http://www.panix.com/~ziggy/parrot.html (no, it's not mine) <obra> mmmm. hawt sysadmin chx0rs <lathos> This is sad. I know of *a* hawt sysamin chx0r. <obra> I know more than a few. <lathos> obra: There are two? Are you sure it's not the same one?
diff -uNrx CVS -x .cvs -x .# /parrot-cvs/MANIFEST /parrot/MANIFEST --- /parrot-cvs/MANIFEST Mon Jan 28 23:28:18 2002 +++ /parrot/MANIFEST Mon Jan 28 23:30:38 2002 @@ -69,6 +69,7 @@ docs/strings.pod docs/tests.pod docs/vtables.pod +embed.c encoding.c encodings/singlebyte.c encodings/utf16.c @@ -106,6 +107,7 @@ hints/vms.pl include/parrot/chartype.h include/parrot/encoding.h +include/parrot/embed.h include/parrot/events.h include/parrot/exceptions.h include/parrot/global_setup.h diff -uNrx CVS -x .cvs -x .# /parrot-cvs/Makefile.in /parrot/Makefile.in --- /parrot-cvs/Makefile.in Mon Jan 28 23:28:18 2002 +++ /parrot/Makefile.in Mon Jan 28 23:28:48 2002 @@ -63,7 +63,7 @@ $(INC)/global_setup.h $(INC)/vtable.h $(INC)/oplib/core_ops.h $(INC)/oplib/core_ops_prederef.h \ $(INC)/runops_cores.h $(INC)/trace.h \ $(INC)/pmc.h $(INC)/key.h $(INC)/resources.h $(INC)/platform.h \ -$(INC)/interp_guts.h ${jit_h} ${jit_struct_h} $(INC)/rx.h $(INC)/rxstacks.h +$(INC)/interp_guts.h ${jit_h} ${jit_struct_h} $(INC)/rx.h $(INC)/rxstacks.h +$(INC)/embed.h CLASS_O_FILES = classes/default$(O) classes/array$(O) \ classes/perlint$(O) classes/perlstring$(O) classes/perlnum$(O) \ @@ -80,7 +80,7 @@ INTERP_O_FILES = exceptions$(O) global_setup$(O) interpreter$(O) parrot$(O) register$(O) \ core_ops$(O) core_ops_prederef$(O) memory$(O) packfile$(O) stacks$(O) \ string$(O) encoding$(O) chartype$(O) runops_cores$(O) trace$(O) pmc$(O) key$(O) \ -platform$(O) ${jit_o} resources$(O) rx$(O) rxstacks$(O) +platform$(O) ${jit_o} resources$(O) rx$(O) rxstacks$(O) embed$(O) O_FILES = $(INTERP_O_FILES) $(IO_O_FILES) $(CLASS_O_FILES) $(ENCODING_O_FILES) $(CHARTYPE_O_FILES) @@ -308,6 +308,8 @@ rxstacks$(O): $(H_FILES) stacks$(O): $(H_FILES) + +embed$(O): $(H_FILES) core_ops$(O): $(H_FILES) core_ops.c diff -uNrx CVS -x .cvs -x .# /parrot-cvs/config_h.in /parrot/config_h.in --- /parrot-cvs/config_h.in Mon Jan 14 01:19:28 2002 +++ /parrot/config_h.in Mon Jan 28 21:48:34 2002 @@ -6,7 +6,11 @@ #if !defined(PARROT_CONFIG_H_GUARD) #define PARROT_CONFIG_H_GUARD + +#if defined(PARROT_IN_CORE + #include <stddef.h> + typedef ${iv} INTVAL; typedef unsigned ${iv} UINTVAL; typedef ${nv} FLOATVAL; @@ -41,11 +45,6 @@ #define JIT_ARCHNAME "${jitarchname}" #define JIT_CAPABLE ${jitcapable} -#define PARROT_VERSION "${VERSION}" -#define PARROT_MAJOR_VERSION ${MAJOR} -#define PARROT_MINOR_VERSION ${MINOR} -#define PARROT_PATCH_VERSION ${PATCH} - #define PARROT_CORE_OPLIB_NAME "core" #define PARROT_CORE_OPLIB_INIT Parrot_DynOp_core_${MAJOR}_${MINOR}_${PATCH} @@ -54,5 +53,12 @@ ${headers} +#endif + +#define PARROT_VERSION "${VERSION}" +#define PARROT_MAJOR_VERSION ${MAJOR} +#define PARROT_MINOR_VERSION ${MINOR} +#define PARROT_PATCH_VERSION ${PATCH} +#define PARROT_ARCHNAME "${jitarchname}" #endif diff -uNrx CVS -x .cvs -x .# /parrot-cvs/embed.c /parrot/embed.c --- /parrot-cvs/embed.c Wed Dec 31 16:00:00 1969 +++ /parrot/embed.c Mon Jan 28 23:23:28 2002 @@ -0,0 +1,183 @@ +#include "parrot/parrot.h" +#include "parrot/embed.h" + +static BOOLVAL world_inited=0; + +struct Parrot_Interp * +Parrot_new() { + return make_interpreter(0); +} + +void +Parrot_init(struct Parrot_Interp *interpreter) { + if(!world_inited) { + world_inited=1; + init_world(); + } +} + +void +Parrot_setflag(struct Parrot_Interp *interpreter, Parrot_flag flag, Parrot_flag_val +value) { + interpreter->flags |= flag; +} + +struct PackFile * +Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) { + /* XXX This ugly mess ought to be cleanupable. */ + int fd; + struct stat file_stat; + + opcode_t program_size; + char *program_code; + struct PackFile *pf; + + if(strcmp(filename, "-")==0) { /* read from STDIN */ + char *cursor; + INTVAL read_result; + + program_size = 0; + + program_code = (char*)malloc(program_size + 1024); + if (NULL == program_code) { + fprintf(stderr, "Parrot VM: Could not allocate buffer to read packfile +from stdin.\n"); + return NULL; + } + cursor = (char*)program_code; + + while ((read_result = read(0, cursor, 1024)) > 0) { + program_size += read_result; + program_code = realloc(program_code, program_size + 1024); + + if (NULL == program_code) { + fprintf(stderr, "Parrot VM: Could not reallocate buffer while reading +packfile from stdin.\n"); + return NULL; + } + + cursor = (char*)program_code + program_size; + } + + if (read_result < 0) { + fprintf(stderr, "Parrot VM: Problem reading packfile from stdin.\n"); + return NULL; + } + } + else { + if (stat(filename, &file_stat)) { + fprintf(stderr, "Parrot VM: Can't stat %s, code %i.\n", filename, errno); + return NULL; + } + fd = open(filename, O_RDONLY); + if (!fd) { + fprintf(stderr, "Parrot VM: Can't open %s, code %i.\n", filename, errno); + return NULL; + } + + program_size = file_stat.st_size; + +#ifndef HAS_HEADER_SYSMMAN + + program_code = (char*)mem_sys_allocate(program_size); + read(fd, (void*)program_code, program_size); + + if (!program_code) { + fprintf(stderr, "Parrot VM: Can't read file %s, code %i.\n", filename, +errno); + return NULL; + } + +#else + + program_code = mmap(0, program_size, PROT_READ, MAP_SHARED, fd, (off_t)0); + + if (!program_code) { + fprintf(stderr, "Parrot VM: Can't read file %s, code %i.\n", filename, +errno); + return NULL; + } + +#endif + + } + + pf = PackFile_new(); + + if(!PackFile_unpack(interpreter, pf, program_code, program_size) ) { + fprintf(stderr, "Parrot VM: Can't unpack packfile %s.\n", filename); + return NULL; + } + + return pf; +} + +void +Parrot_loadbc(struct Parrot_Interp *interpreter, struct PackFile *pf) { + interpreter->code=pf; +} + +void +Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) { + if(interpreter->flags & PARROT_DEBUG_FLAG) { + fprintf(stderr, "Parrot VM: Debugging enabled.\n"); + + if(interpreter->flags & PARROT_BOUNDS_FLAG) { + fprintf(stderr, "Parrot VM: Bounds checking enabled.\n"); + } + if(interpreter->flags & PARROT_PREDEREF_FLAG) { + fprintf(stderr, "Parrot VM: Predereferencing enabled.\n"); + } + if(interpreter->flags & PARROT_JIT_FLAG) { + fprintf(stderr, "Parrot VM: JIT enabled.\n"); + } + } + + if(!JIT_CAPABLE && interpreter->flags & PARROT_JIT_FLAG) { + fprintf(stderr, "Parrot VM: Platform " JIT_ARCHNAME " is not JIT-capable.\n"); + exit(1); + } + + runops(interpreter, interpreter->code, 0); + + /* + ** If any profile information was gathered, print it out: + */ + + if (interpreter->profile != NULL) { + unsigned int j; + int op_count = 0; + int call_count = 0; + FLOATVAL time = 0.0; + + printf("Operation profile:\n\n"); + + printf(" CODE OP FULL NAME CALLS TOTAL TIME AVG TIME \n"); + printf(" ----- ------------ ------------ ---------- ----------\n"); + + for (j = 0; j < interpreter->op_count; j++) { + if(interpreter->profile[j].numcalls > 0) { + op_count++; + call_count += interpreter->profile[j].numcalls; + time += interpreter->profile[j].time; + + printf(" %5d %-12s %12ld %5.6f %5.6f\n", j, + interpreter->op_info_table[j].full_name, + interpreter->profile[j].numcalls, + interpreter->profile[j].time, + interpreter->profile[j].time / +(FLOATVAL)interpreter->profile[j].numcalls + ); + } + } + + printf(" ----- ------------ ------------ ---------- ----------\n"); + printf(" %5d %-12s %12d %5.6f %5.6f\n", + op_count, + "", + call_count, + time, + time / (FLOATVAL)call_count + ); + } +} + +void +Parrot_destroy(struct Parrot_Interp *interp) { + free(interp); +} + diff -uNrx CVS -x .cvs -x .# /parrot-cvs/include/parrot/embed.h /parrot/include/parrot/embed.h --- /parrot-cvs/include/parrot/embed.h Wed Dec 31 16:00:00 1969 +++ /parrot/include/parrot/embed.h Mon Jan 28 21:49:04 2002 @@ -0,0 +1,35 @@ +#if !defined(PARROT_EMBED_H_GUARD) +#define PARROT_EMBED_H_GUARD + +#include "parrot/config.h" + +typedef int Parrot_flag; +typedef void * Parrot_flag_val; + +/* plucked these straight from interpreter.h */ +#define PARROT_DEBUG_FLAG 0x01 /* We're debugging */ +#define PARROT_TRACE_FLAG 0x02 /* We're tracing execution */ +#define PARROT_BOUNDS_FLAG 0x04 /* We're tracking byte code bounds */ +#define PARROT_PROFILE_FLAG 0x08 /* We're gathering profile information */ +#define PARROT_PREDEREF_FLAG 0x10 /* We're using the prederef runops */ +#define PARROT_JIT_FLAG 0x20 /* We're using the jit runops */ + +/* These two are basically Magic Cookies to the outside world. */ +struct Parrot_Interp; +struct PackFile; + +struct Parrot_Interp *interp_new(); + +void Parrot_init(struct Parrot_Interp *); + +void Parrot_setflag(struct Parrot_Interp *, Parrot_flag, Parrot_flag_val); + +struct PackFile * Parrot_readbc(struct Parrot_Interp *, char *); + +void Parrot_loadbc(struct Parrot_Interp *, struct PackFile *); + +void Parrot_runcode(struct Parrot_Interp *, int argc, char *argv[]); + +void Parrot_destroy(struct Parrot_Interp *); + +#endif \ No newline at end of file diff -uNrx CVS -x .cvs -x .# /parrot-cvs/include/parrot/parrot.h /parrot/include/parrot/parrot.h --- /parrot-cvs/include/parrot/parrot.h Mon Jan 28 23:28:22 2002 +++ /parrot/include/parrot/parrot.h Mon Jan 28 23:28:54 2002 @@ -24,6 +24,8 @@ #define VAR_SCOPE extern #endif +#define PARROT_IN_CORE + #include "parrot/config.h" #include <stdlib.h> diff -uNrx CVS -x .cvs -x .# /parrot-cvs/test_main.c /parrot/test_main.c --- /parrot-cvs/test_main.c Mon Jan 28 23:28:18 2002 +++ /parrot/test_main.c Mon Jan 28 23:23:32 2002 @@ -1,7 +1,7 @@ /* test_main.c * Copyright: (When this is determined...it will go here) * CVS Info - * $Id: test_main.c,v 1.39 2002/01/28 15:59:28 simon Exp $ + * $Id: test_main.c,v 1.35 2002/01/14 20:03:52 dan Exp $ * Overview: * A sample test program * Data Structure and Algorithms: @@ -9,244 +9,126 @@ * Notes: * References: */ +#include "parrot/embed.h" +#include <stdio.h> -#include "parrot/parrot.h" +#define setopt(flag) Parrot_setflag(interpreter, flag, (*argv)[0]+2); -#include "parrot/oplib/core_ops.h" +char * +parseflags(struct Parrot_Interp *interpreter, int *argc, char **argv[]); + +void +usage(); + +void +version(); int -main(int argc, char **argv) { - int i; - int flags; - int bounds_checking; - int profiling; - int tracing; - int debugging; - int predereferencing; - int jit; - int from_stdin; - int from_file; +main(int argc, char *argv[]) { + struct Parrot_Interp *interpreter; char *filename; - char **argp; + struct PackFile *pf; + + interpreter=Parrot_new(); - struct Parrot_Interp *interpreter; - init_world(); - - /* - ** Look for the switches: - ** - ** -d debugging - ** -b bounds checking - ** -j JIT - ** -p profiling - ** -P predereferencing - ** -t tracing - ** -f filename or stdin - ** - */ - argp = argv+1; - flags = 0; - bounds_checking = 0; - profiling = 0; - tracing = 0; - debugging = 0; - predereferencing = 0; - jit = 0; - from_stdin = 0; - from_file = 0; - filename = NULL; - - while (*argp && (*argp)[0] == '-') { - if((*argp)[2] != '\0') - internal_exception(PARROT_USAGE_ERROR, - "%s: Invalid switch: %s\n", argv[0], (*argp)); - - switch((*argp)[1]) { - case 'd': debugging = 1; - argp++; break; - case 'b': bounds_checking = 1; - argp++; break; - case 'j': jit = 1; - argp++; break; - case 'p': profiling = 1; - argp++; break; - case 'P': predereferencing = 1; - argp++; break; - case 't': tracing = 1; - argp++; break; - case 'f': if(*(++argp) == NULL) - internal_exception(PARROT_USAGE_ERROR, - "%s: -f requires an argument\n", - argv[0]); - - if(strcmp("-", (*argp)) == 0) { - from_stdin = 1; - } else { - filename = malloc(strlen((*argp))+1); - filename = strcpy(filename, (*argp)); - } - argp++; break; - default: - internal_exception(PARROT_USAGE_ERROR, - "%s: Invalid switch: %s\n", - argv[0], (*argp)); - } + if(!interpreter) { + return 1; } - if (debugging) flags |= PARROT_DEBUG_FLAG; - if (profiling) flags |= PARROT_PROFILE_FLAG; - if (predereferencing) flags |= PARROT_PREDEREF_FLAG; - if (tracing) flags |= PARROT_TRACE_FLAG; - if (bounds_checking) flags |= PARROT_BOUNDS_FLAG; - if (jit) flags |= PARROT_JIT_FLAG; - -#if !JIT_CAPABLE - if(jit) - internal_exception( JIT_UNAVAILABLE, "%s: Cannot use the '-j' JIT-enabling flag on this architecture: " JIT_ARCHNAME "\n", argv[0]); -#endif + Parrot_init(interpreter); - if(debugging) - fprintf(stderr, "Parrot VM: Debugging enabled.\n"); + filename=parseflags(interpreter, &argc, &argv); - interpreter = make_interpreter(flags); - - /* If we got only the program name, complain */ + pf=Parrot_readbc(interpreter, filename); - if (*argp == NULL && !filename && !from_stdin) { - internal_exception(PARROT_USAGE_ERROR, "%s: usage: %s prog\n", argv[0], argv[0]); + if(!pf) { + return 1; } - /* Otherwise load in the program they gave and try that, or - */ - else { - opcode_t *program_code; -#ifdef __LCC__ - /* work around for a code generation bug in our lcc test environment */ - int program_size; -#else - size_t program_size; -#endif - struct stat file_stat; - int fd; - struct PackFile * pf; - - if (from_stdin) { - char *cursor; - INTVAL read_result; - - program_size = 0; - - program_code = (opcode_t*)malloc(program_size + 1024); - if (NULL == program_code) { - fprintf(stderr, "Could not allocate buffer to read stdin\n"); - } - cursor = (char*)program_code; - - while ((read_result = read(0, cursor, 1024)) > 0) { - program_size += read_result; - program_code = realloc(program_code, program_size + 1024); - if (NULL == program_code) { - fprintf(stderr, - "Could not reallocate buffer to read stdin\n"); - } - cursor = (char*)program_code + program_size; - } - - if (read_result < 0) { - internal_exception(PIO_ERROR,"Problem reading from stdin\n"); - } - } - else { /* read from file */ - if (!filename) { - filename = malloc(strlen((*argp))+1); - strcpy(filename, (*argp)); - } - - if (stat(filename, &file_stat)) { - printf("can't stat %s, code %i\n", filename, errno); - return 1; - } - if (!S_ISREG(file_stat.st_mode)) { - printf("%s is not a regular file\n", filename); - return 1; - } - fd = open(filename, O_RDONLY); - if (!fd) { - printf("Can't open, error %i\n", errno); - return 1; - } - - program_size = file_stat.st_size; - -#ifndef HAS_HEADER_SYSMMAN - program_code = (opcode_t*)mem_sys_allocate(program_size); - read(fd, (void*)program_code, program_size); -#else - program_code = - (opcode_t *) mmap(0, program_size, PROT_READ, - MAP_SHARED, fd, (off_t)0); -#endif - } /* end reading from file */ - - if (!program_code) { - printf("Can't mmap, code %i\n", errno); - return 1; - } - - pf = PackFile_new(); - if( !PackFile_unpack(interpreter, pf, (char *)program_code, - (size_t)program_size) ) { - printf( "Can't unpack.\n" ); - return 1; - } - /* - ** Run the interpreter loop: - */ - - runops(interpreter, pf, 0); - - /* - ** If any profile information was gathered, print it out: - */ - - if (interpreter->profile != NULL) { - unsigned int j; - int op_count = 0; - int call_count = 0; - FLOATVAL sum_time = 0.0; - - printf("Operation profile:\n\n"); - - printf(" CODE OP FULL NAME CALLS TOTAL TIME AVG TIME \n"); - printf(" ----- ------------ ------------ ---------- ----------\n"); - - for (j = 0; j < interpreter->op_count; j++) { - if(interpreter->profile[j].numcalls > 0) { - op_count++; - call_count += interpreter->profile[j].numcalls; - sum_time += interpreter->profile[j].time; - - printf(" %5d %-12s %12ld %5.6f %5.6f\n", j, - interpreter->op_info_table[j].full_name, - interpreter->profile[j].numcalls, - interpreter->profile[j].time, - interpreter->profile[j].time / (FLOATVAL)interpreter->profile[j].numcalls - ); - } - - } - - printf(" ----- ------------ ------------ ---------- ----------\n"); - printf(" %5d %-12s %12d %5.6f %5.6f\n", - op_count, - "", - call_count, - sum_time, - sum_time / (FLOATVAL)call_count - ); + Parrot_loadbc(interpreter, pf); + Parrot_runcode(interpreter, argc, argv); + Parrot_destroy(interpreter); + + return 0; +} + +char * +parseflags(struct Parrot_Interp *interpreter, int *argc, char **argv[]) { + if(*argc==1) { + usage(); + } + + /* skip the program name arg */ + (*argc)--; + (*argv)++; + + while ((*argc) && (*argv)[0][0] == '-') { + switch((*argv)[0][1]) { + case 'b': + setopt(PARROT_BOUNDS_FLAG); break; + case 'j': + setopt(PARROT_JIT_FLAG); break; + case 'p': + setopt(PARROT_PROFILE_FLAG); break; + case 'P': + setopt(PARROT_PREDEREF_FLAG); break; + case 't': + setopt(PARROT_TRACE_FLAG); break; + case 'd': + setopt(PARROT_DEBUG_FLAG); break; + case 'h': + usage(); break; + case 'v': + version(); break; + case '-': + (*argc)--; + (*argv)++; + goto OUT; + case '\0': /* bare '-' means read from stdin */ + goto OUT; + default: + fprintf(stderr, "test_parrot: Invalid flag %c used", (*argv)[0][1]); + exit(1); } + + (*argc)--; + (*argv)++; } + +OUT: + (*argc)--; + return (*(argv++))[0]; +} + +void usage() { + fprintf(stderr, +"Usage: test_parrot [switches] [--] programfile [arguments]\n\ + -b Activate bounds checks\n\ + -d Activate debugging\n\ + -h Display this message\n\ + -j Activate Just-In-Time compiler\n\ + -p Activate profiling\n\ + -P Activate predereferencing\n\ + -t Activate tracing\n\ + -v Display version information\n\n"); + + exit(0); +} + +void version() { + fprintf(stderr, +"This is parrot version " PARROT_VERSION " (with development patches) built for " +PARROT_ARCHNAME "\n\ +Copyright (C) 2001-2002 Yet Another Society. All Rights Reserved.\n\ +\n\ +Parrot may be copied only under the terms of either the Artistic License or the\n\ +GNU General Public License, which may be found in the Parrot source kit.\n\ +\n\ +This program is distributed in the hope that it will be useful,\n\ +but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either\n\ +the GNU General Public License or the Artistic License for more details.\n\n"); - return 0; + exit(0); } /*