diff --git a/MANIFEST b/MANIFEST index ff809f0d86..b66414d1c4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -585,6 +585,8 @@ rx.c rx.ops rxstacks.c smallobject.c +spf_render.c +spf_vtable.c stacks.c string.c sub.c diff --git a/config/auto/sizes.pl b/config/auto/sizes.pl index bd4b2b7871..41af8e9084 100644 --- a/config/auto/sizes.pl +++ b/config/auto/sizes.pl @@ -41,6 +41,68 @@ sub runstep { still compile and run, but you may see a ton of warnings. END } + + #Get HUGEINTVAL + if(my $size=eval { + open(TEST, ">test.c") or die "Can't open test.c: $!"; + print TEST <<'END'; +#include + +int main() { + long long foo; + printf("%u", sizeof(foo)); + return 0; +} +END + close TEST; + + cc_build(); + cc_run(); + }) { + Configure::Data->set( + 'hugeintval' => 'long long', + 'hugeintvalsize' => $size + ); + } + else { + Configure::Data->set( + 'hugeintval' => 'long', + 'hugeintvalsize' => Configure::Data->get('longsize') + ); + } + + cc_clean(); + + #get HUGEFLOATVAL + if(my $size=eval { + open(TEST, ">test.c") or die "Can't open test.c: $!"; + print TEST <<'END'; +#include + +int main() { + long double foo; + printf("%u", sizeof(foo)); + return 0; +} +END + close TEST; + + cc_build(); + cc_run(); + }) { + Configure::Data->set( + 'hugefloatval' => 'long double', + 'hugefloatvalsize' => $size + ); + } + else { + Configure::Data->set( + 'hugefloatval' => 'double', + 'hugefloatvalsize' => Configure::Data->get('doublesize') + ); + } + + cc_clean(); } 1; diff --git a/config/gen/config_h/config_h.in b/config/gen/config_h/config_h.in index 6a2274790f..4cf811c072 100644 --- a/config/gen/config_h/config_h.in +++ b/config/gen/config_h/config_h.in @@ -48,6 +48,10 @@ typedef Parrot_Int INTVAL; typedef Parrot_UInt UINTVAL; typedef Parrot_Float FLOATVAL; +typedef ${hugeintval} HUGEINTVAL; +typedef unsigned ${hugeintval} UHUGEINTVAL; +typedef ${hugefloatval} HUGEFLOATVAL; + #define INTVAL_SIZE ${intvalsize} #define NUMVAL_SIZE ${nvsize} #define OPCODE_T_SIZE ${opcode_t_size} diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in index a07b6045a5..e40be06e7c 100644 --- a/config/gen/makefiles/root.in +++ b/config/gen/makefiles/root.in @@ -96,10 +96,11 @@ INTERP_O_FILES = exceptions$(O) global_setup$(O) interpreter$(O) parrot$(O) \ packfile$(O) stacks$(O) string$(O) sub$(O) encoding$(O) \ chartype$(O) runops_cores$(O) trace$(O) pmc$(O) key$(O) hash$(O) \ core_pmcs$(O) platform$(O) ${jit_o} \ - ${gc_o} rx$(O) rxstacks$(O) intlist$(O) \ - embed$(O) warnings$(O) misc$(O) ${cg_o} \ + ${gc_o} rx$(O) rxstacks$(O) intlist$(O) \ + embed$(O) warnings$(O) ${cg_o} \ packout$(O) byteorder$(O) debug$(O) smallobject$(O) \ - headers$(O) dod$(O) method_util$(O) + headers$(O) dod$(O) method_util$(O) \ + misc$(O) spf_render$(O) spf_vtable$(O) O_FILES = $(INTERP_O_FILES) \ $(IO_O_FILES) \ @@ -122,7 +123,7 @@ OPS_FILES = ${ops} $(GEN_OPSFILES) CFLAGS = ${ccflags} ${cc_warn} ${cc_inc} ${cc_hasjit} ${cg_flag} ${gc_flag} LINKFLAGS = ${linkflags} -LDFLAGS = ${ldflags} +LDFLAGS = ${ldflags} ${ld_debug} C_LIBS = ${libs} @@ -418,9 +419,13 @@ ${cg_c} ${gc_c} -warnings$(O) : $(H_FILES) +warnings$(O) : $(GENERAL_H_FILES) -misc$(O) : $(H_FILES) +misc$(O) : $(GENERAL_H_FILES) + +spf_render$(O) : $(GENERAL_H_FILES) + +spf_vtable$(O) : $(GENERAL_H_FILES) # $(STICKY_FILES) : Configure.pl # $(PERL) Configure.pl diff --git a/config/gen/platform/ansi.c b/config/gen/platform/ansi.c index 778f439255..909425fad7 100644 --- a/config/gen/platform/ansi.c +++ b/config/gen/platform/ansi.c @@ -27,7 +27,7 @@ Parrot_floatval_time(void) { /* unable to provide this level of precision under ANSI-C, so just fall back to intval time for this. */ - fprintf(stderr, "[ANSI] Parrot_floatval_time not accurate!\n"); + Parrot_warn_c(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_floatval_time not accurate"); return (FLOATVAL)Parrot_intval_time(); } @@ -39,7 +39,7 @@ Parrot_floatval_time(void) void Parrot_sleep(unsigned int seconds) { - fprintf(stderr, "[ANSI] Parrot_sleep not implemented!\n"); + Parrot_warn_c(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_sleep not implemented"); return; } @@ -50,7 +50,7 @@ Parrot_sleep(unsigned int seconds) void Parrot_setenv(const char *name, const char *value) { - fprintf(stderr, "[ANSI] Parrot_setenv not implemented!\n"); + Parrot_warn_c(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_setenv not implemented"); return; } @@ -62,7 +62,7 @@ Parrot_setenv(const char *name, const char *value) void * Parrot_dlopen(const char *filename) { - fprintf(stderr, "[ANSI] Parrot_dlopen not implemented!\n"); + Parrot_warn_c(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_dlopen not implemented"); return NULL; } @@ -74,7 +74,7 @@ Parrot_dlopen(const char *filename) const char * Parrot_dlerror(void) { - return "[ANSI] Parrot_dlerror not implemented!\n"; + return "Parrot_dlerror not implemented"; } @@ -85,7 +85,7 @@ Parrot_dlerror(void) void * Parrot_dlsym(void *handle, const char *symbol) { - fprintf(stderr, "[ANSI] Parrot_dlsym not implemented!\n"); + Parrot_warn_c(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_dlsym not implemented"); return NULL; } @@ -97,7 +97,7 @@ Parrot_dlsym(void *handle, const char *symbol) int Parrot_dlclose(void *handle) { - fprintf(stderr, "[ANSI] Parrot_dlclose not implemented!\n"); + Parrot_warn_c(NULL, PARROT_WARNINGS_PLATFORM_FLAG, "Parrot_dlclose not implemented"); return 0; } diff --git a/config/init/hints/mswin32.pl b/config/init/hints/mswin32.pl index 81f1c37052..462f3f89cf 100644 --- a/config/init/hints/mswin32.pl +++ b/config/init/hints/mswin32.pl @@ -18,6 +18,7 @@ # The logo gets printed to STDERR; hence the redirection. my $cc_output = `$cc 2>&1`; $ccflags =~ s/-O1 // if $cc_output =~ m/Standard/; + Configure::Data->set( so => '.dll', @@ -26,7 +27,8 @@ cc_o_out => '-Fo', cc_exe_out => '-Fe', cc_ldflags => '/link', - cc_debug => '-Zi', + #Use Edit and Continue debugging if available + cc_debug => ($cc_output =~ /-ZI/? '-ZI' : '-Zi'), ld_debug => '-debug', ld_shared => '-dll', ld_shared_flags=> '-def:libparrot.def', diff --git a/core.ops b/core.ops index 7b9d3a5fb0..28829f8441 100644 --- a/core.ops +++ b/core.ops @@ -2155,8 +2155,38 @@ inline op pack(inout STR, in INT, in INT, in INT) { goto NEXT(); } +=item C(out STR, in STR, in PMC) + +=item C(out PMC, in PMC, in PMC) + +=item C(out STR, in STR) [unimplemented] + +=item C(out PMC, in PMC) [unimplemented] + +Sets $1 to the result of calling C with the +given format ($2) and arguments ($3, which should be an ordered +aggregate PMC). In the (unimplemented) versions that don't include +$3, arguments are popped off the user stack. + +The result is quite similar to using the system C, but is +protected against buffer overflows and the like. There are some +differences, especially concerning sizes (which are largely ignored); +see F for details. + =back +inline op sprintf(out STR, in STR, in PMC) { + $1=Parrot_psprintf(interpreter, $2, $3); + goto NEXT(); +} + +inline op sprintf(out PMC, in PMC, in PMC) { + $1->vtable->set_string_native(interpreter, $1, + Parrot_psprintf(interpreter, $2->vtable->get_string(interpreter, $2), $3) + ); + goto NEXT(); +} + =cut ############################################################################### diff --git a/debug.c b/debug.c index 403c051a05..48acde985f 100644 --- a/debug.c +++ b/debug.c @@ -215,18 +215,18 @@ PDB_get_command(struct Parrot_Interp *interpreter) while (pdb->cur_opcode != line->opcode) line = line->next; - fprintf(stderr,"\n%li ",line->number); + PIO_eprintf(interpreter, "\n%li ", line->number); c = pdb->file->source + line->source_offset; while (*c != '\n' && c) - fprintf(stderr,"%c",*(c++)); - fprintf(stderr,"\n"); + PIO_eprintf(interpreter, "%c", *(c++)); + PIO_eprintf(interpreter, "\n"); } i = 0; c = (char *)mem_sys_allocate(255); - fprintf(stderr,"\n(pdb) "); + PIO_eprintf(interpreter, "\n(pdb) "); /* skip leading whitespace */ do { @@ -331,7 +331,7 @@ PDB_run_command(struct Parrot_Interp *interpreter, const char *command) PDB_run_command(interpreter,pdb->last_command); break; default: - fprintf(stderr,"Undefined command: \"%s\". Try \"help\".", + PIO_eprintf(interpreter, "Undefined command: \"%s\". Try \"help\".", command); break; } @@ -448,7 +448,7 @@ PDB_cond(struct Parrot_Interp *interpreter, const char *command) condition->type = PDB_cond_pmc; break; default: - fprintf(stderr, "First argument must be a register\n"); + PIO_eprintf(interpreter, "First argument must be a register\n"); return NULL; } @@ -496,7 +496,7 @@ PDB_cond(struct Parrot_Interp *interpreter, const char *command) goto INV_COND; break; default: -INV_COND: fprintf(stderr, "Invalid condition\n"); +INV_COND: PIO_eprintf(interpreter, "Invalid condition\n"); return NULL; } @@ -580,7 +580,7 @@ PDB_set_break(struct Parrot_Interp *interpreter, const char *command) /* Abort if the line number provided doesn't exists */ if (!line->next) { - fprintf(stderr,"Can't set a breakpoint at line number %li\n",ln); + PIO_eprintf(interpreter, "Can't set a breakpoint at line number %li\n",ln); return; } } @@ -605,13 +605,13 @@ PDB_set_break(struct Parrot_Interp *interpreter, const char *command) /* Revive the breakpoint if was deleted */ if (sbreak && sbreak->skip == -1) { - fprintf(stderr,"Breakpoint %li at line %li\n",i,line->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Breakpoint %li at line %li\n",i,line->number); sbreak->skip = 0; return; } /* Don't do anything if there is already a breakpoint at this line */ if (sbreak) { - fprintf(stderr,"Breakpoint %li already at line %li\n",i,line->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Breakpoint %li already at line %li\n",i,line->number); return; } @@ -648,7 +648,7 @@ PDB_set_break(struct Parrot_Interp *interpreter, const char *command) pdb->breakpoint = newbreak; } - fprintf(stderr,"Breakpoint %li at line %li\n",i,line->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Breakpoint %li at line %li\n",i,line->number); } /* PDB_init @@ -694,7 +694,7 @@ PDB_init(struct Parrot_Interp *interpreter, const char *command) /* Restart if we are already running */ if (pdb->state & PDB_RUNNING) - fprintf(stderr,"Restating\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Restating\n"); /* Get the bytecode start */ pdb->cur_opcode = interpreter->code->byte_code; @@ -715,7 +715,7 @@ PDB_continue(struct Parrot_Interp *interpreter, /* Skip any breakpoint? */ if (command && *command) { if (!pdb->breakpoint) { - fprintf(stderr,"No breakpoints to skip\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"No breakpoints to skip\n"); return; } ln = atol(command); @@ -769,7 +769,7 @@ PDB_program_end(struct Parrot_Interp *interpreter) /* Remove the RUNNING state */ pdb->state &= ~PDB_RUNNING; - fprintf(stderr,"Program exited.\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Program exited.\n"); return 1; } @@ -1258,7 +1258,7 @@ PDB_disassemble(struct Parrot_Interp *interpreter, const char *command) pline = pline->next; if (!(pline)) { - fprintf(stderr,"Label number %li out of bounds.\n",label->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Label number %li out of bounds.\n",label->number); return; } @@ -1363,7 +1363,7 @@ PDB_load_source(struct Parrot_Interp *interpreter, const char *command) /* abort if fopen failed */ if (!file) { - fprintf(stderr,"Unable to load %s\n", f); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Unable to load %s\n", f); return; } @@ -1461,14 +1461,14 @@ PDB_list(struct Parrot_Interp *interpreter, const char *command) i = 1; while (line->next) { - fprintf(stderr,"%li ",pdb->file->list_line + i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%li ",pdb->file->list_line + i); /* If it has a label print it */ if (line->label) - fprintf(stderr,"L%li:\t",line->label->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"L%li:\t",line->label->number); c = pdb->file->source + line->source_offset; while (*c != '\n') - fprintf(stderr,"%c",*(c++)); - fprintf(stderr,"\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%c",*(c++)); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\n"); line = line->next; if (i++ == n) break; @@ -1501,7 +1501,7 @@ PDB_eval(struct Parrot_Interp *interpreter, const char *command) /* Find the opcode number */ op_number = interpreter->op_lib->op_code(buf, 1); if (op_number < 0) { - fprintf(stderr, "Invalid opcode '%s'\n", buf); + PIO_eprintf(interpreter, "Invalid opcode '%s'\n", buf); return; } /* Start generating the bytecode */ @@ -1619,7 +1619,7 @@ PDB_print_stack(struct Parrot_Interp *interpreter, const char *command) PDB_print_stack_pmc(interpreter, command); break; default: - fprintf(stderr,"Unknown argument \"%s\" to 'stack'\n", command); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Unknown argument \"%s\" to 'stack'\n", command); break; } } @@ -1638,14 +1638,14 @@ PDB_print_stack_int(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_INT_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"Integer stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Integer stack, frame %li, depth %li\n", i, depth); na(command); - PDB_print_int(&chunk->IReg[depth], atoi(command)); + PDB_print_int(interpreter, &chunk->IReg[depth], atoi(command)); } /* PDB_print_stack_num @@ -1661,14 +1661,14 @@ PDB_print_stack_num(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_NUM_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"Float stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Float stack, frame %li, depth %li\n", i, depth); na(command); - PDB_print_num(&chunk->NReg[depth], atoi(command)); + PDB_print_num(interpreter, &chunk->NReg[depth], atoi(command)); } /* PDB_print_stack_string @@ -1684,11 +1684,11 @@ PDB_print_stack_string(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_STR_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"String stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"String stack, frame %li, depth %li\n", i, depth); na(command); PDB_print_string(interpreter,&chunk->SReg[depth], atoi(command)); @@ -1707,11 +1707,11 @@ PDB_print_stack_pmc(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_PMC_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"PMC stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"PMC stack, frame %li, depth %li\n", i, depth); na(command); PDB_print_pmc(interpreter,&chunk->PReg[depth], atoi(command), NULL); @@ -1721,14 +1721,13 @@ static void dump_string(struct Parrot_Interp *interpreter, STRING* s) { if (s) { - fprintf(stderr,"\tBuflen =\t%12ld\n",s->buflen); - fprintf(stderr,"\tFlags =\t%12ld\n",s->flags); - fprintf(stderr,"\tBufused =\t%12ld\n",s->bufused); - fprintf(stderr,"\tStrlen =\t%12ld\n",s->strlen); - fprintf(stderr,"\tOffset =\t%12d\n", + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tBuflen =\t%12ld\n",s->buflen); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tFlags =\t%12ld\n",s->flags); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tBufused =\t%12ld\n",s->bufused); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tStrlen =\t%12ld\n",s->strlen); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tOffset =\t%12d\n", (char*) s->strstart - (char*) s->bufstart); - fprintf(stderr,"\tString =\t%s\n", - string_to_cstring(interpreter, s)); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tString =\t%S\n", s); } } @@ -1749,31 +1748,26 @@ PDB_print_user_stack(struct Parrot_Interp *interpreter, const char *command) switch (entry->entry_type) { case STACK_ENTRY_INT: - fprintf(stderr,"Integer\t=\t%8li\n",entry->entry.int_val); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Integer\t=\t%8vi\n",entry->entry.int_val); break; case STACK_ENTRY_FLOAT: - fprintf(stderr,"Float\t=\t%8.4f\n",entry->entry.num_val); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Float\t=\t%8.4vf\n",entry->entry.num_val); break; case STACK_ENTRY_STRING: - fprintf(stderr,"String =\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"String =\n"); dump_string(interpreter, entry->entry.string_val); break; case STACK_ENTRY_PMC: - fprintf(stderr,"PMC =\n"); - s = (entry->entry.pmc_val->vtable->get_string( - interpreter, entry->entry.pmc_val)); - - if (s) - fprintf(stderr,"%s\n", string_to_cstring(interpreter, (s))); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"PMC =\n%PS\n", entry->entry.pmc_val); break; case STACK_ENTRY_POINTER: - fprintf(stderr,"POINTER\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"POINTER\n"); break; case STACK_ENTRY_DESTINATION: - fprintf(stderr,"DESTINATION\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"DESTINATION\n"); break; default: - fprintf(stderr,"Invalid stack_entry_type!\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Invalid stack_entry_type!\n"); break; } } @@ -1812,11 +1806,11 @@ PDB_print(struct Parrot_Interp *interpreter, const char *command) switch (c) { case c_i: case c_int: - PDB_print_int(&interpreter->ctx.int_reg, regnum); + PDB_print_int(interpreter, &interpreter->ctx.int_reg, regnum); break; case c_n: case c_num: - PDB_print_num(&interpreter->ctx.num_reg, regnum); + PDB_print_num(interpreter, &interpreter->ctx.num_reg, regnum); break; case c_s: case c_str: @@ -1827,7 +1821,7 @@ PDB_print(struct Parrot_Interp *interpreter, const char *command) PDB_print_pmc(interpreter,&interpreter->ctx.pmc_reg, regnum, key); break; default: - fprintf(stderr, "Unrecognized print option: must be 'int', 'num', 'str', 'pmc', or a register\n"); + PIO_eprintf(interpreter, "Unrecognized print option: must be 'int', 'num', 'str', 'pmc', or a register\n"); } interpreter->DOD_block_level--; @@ -1837,7 +1831,7 @@ PDB_print(struct Parrot_Interp *interpreter, const char *command) * print the whole or a specific value of a integer register structure. */ void -PDB_print_int(struct IReg *int_reg, int regnum) +PDB_print_int(struct Parrot_Interp *interpreter, struct IReg *int_reg, int regnum) { int i,j = 0, k = NUM_REGISTERS; @@ -1846,10 +1840,10 @@ PDB_print_int(struct IReg *int_reg, int regnum) k = regnum + 1; } - fprintf(stderr,"Integer Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Integer Registers:\n"); for (i = j; i < k; i++) { - fprintf(stderr,"I%i =\t",i); - fprintf(stderr,"%11li\n",int_reg->registers[i]); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"I%i =\t",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%11vi\n",int_reg->registers[i]); } } @@ -1857,7 +1851,7 @@ PDB_print_int(struct IReg *int_reg, int regnum) * print the whole or a specific value of a float register structure. */ void -PDB_print_num(struct NReg *num_reg, int regnum) +PDB_print_num(struct Parrot_Interp *interpreter, struct NReg *num_reg, int regnum) { int i,j = 0, k = NUM_REGISTERS; @@ -1866,10 +1860,10 @@ PDB_print_num(struct NReg *num_reg, int regnum) k = regnum + 1; } - fprintf(stderr,"Float Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Float Registers:\n"); for (i = j; i < k; i++) { - fprintf(stderr,"N%i =\t",i); - fprintf(stderr,"%20.4f\n",num_reg->registers[i]); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"N%i =\t",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%20.4f\n",num_reg->registers[i]); } } @@ -1888,9 +1882,9 @@ PDB_print_string(struct Parrot_Interp *interpreter, struct SReg *string_reg, k = regnum + 1; } - fprintf(stderr,"String Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"String Registers:\n"); for (i = j; i < k; i++) { - fprintf(stderr,"S%i =\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"S%i =\n",i); dump_string(interpreter, string_reg->registers[i]); } } @@ -1901,16 +1895,12 @@ print_pmc(struct Parrot_Interp *interpreter, PMC* pmc) if (pmc && pmc->vtable) { STRING* s = pmc->vtable->name(interpreter, pmc); if (s) { - fprintf(stderr, " [%s]\n", string_to_cstring(interpreter, s)); - } - s = (pmc->vtable->get_string(interpreter, pmc)); - if (s) { - fprintf(stderr,"Stringified: %s\n", - string_to_cstring(interpreter, s)); + PIO_eprintf(interpreter, " [%S]\n", s); } + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Stringified: %PS\n", pmc); } else { - fprintf(stderr, "\n"); + PIO_eprintf(interpreter, "\n"); } } @@ -1927,14 +1917,14 @@ PDB_print_pmc(struct Parrot_Interp *interpreter, struct PReg *pmc_reg, } if (regnum == -1) - fprintf(stderr,"PMC Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"PMC Registers:\n"); for (i = j; i < k; i++) { PMC* pmc = pmc_reg->registers[i]; - fprintf(stderr,"P%i", i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"P%i", i); if (key) trace_key_dump(interpreter, key); - fprintf(stderr," ="); + PIO_fprintf(interpreter, PIO_STDERR(interpreter)," ="); if (key) pmc = pmc->vtable->get_pmc_keyed(interpreter, pmc, key); print_pmc(interpreter, pmc); @@ -1947,17 +1937,17 @@ PDB_print_pmc(struct Parrot_Interp *interpreter, struct PReg *pmc_reg, void PDB_info(struct Parrot_Interp *interpreter) { - fprintf(stderr, "Total memory allocated = %d\n", + PIO_eprintf(interpreter, "Total memory allocated = %d\n", interpreter->memory_allocated); - fprintf(stderr, "DOD runs = %d\n", interpreter->dod_runs); - fprintf(stderr, "Collect runs = %d\n", interpreter->collect_runs); - fprintf(stderr, "Active PMCs = %d\n", interpreter->active_PMCs); - fprintf(stderr, "Active buffers = %d\n", interpreter->active_Buffers); - fprintf(stderr, "Total PMCs = %d\n", interpreter->total_PMCs); - fprintf(stderr, "Total buffers = %d\n", interpreter->total_Buffers); - fprintf(stderr, "Header allocations since last collect = %d\n", + PIO_eprintf(interpreter, "DOD runs = %d\n", interpreter->dod_runs); + PIO_eprintf(interpreter, "Collect runs = %d\n", interpreter->collect_runs); + PIO_eprintf(interpreter, "Active PMCs = %d\n", interpreter->active_PMCs); + PIO_eprintf(interpreter, "Active buffers = %d\n", interpreter->active_Buffers); + PIO_eprintf(interpreter, "Total PMCs = %d\n", interpreter->total_PMCs); + PIO_eprintf(interpreter, "Total buffers = %d\n", interpreter->total_Buffers); + PIO_eprintf(interpreter, "Header allocations since last collect = %d\n", interpreter->header_allocs_since_last_collect); - fprintf(stderr, "Memory allocations since last collect = %d\n", + PIO_eprintf(interpreter, "Memory allocations since last collect = %d\n", interpreter->mem_allocs_since_last_collect); } @@ -1968,23 +1958,24 @@ PDB_info(struct Parrot_Interp *interpreter) void PDB_help(const char *command) { - fprintf(stderr,"List of commands:\n"); - fprintf(stderr,"\tdisassemble -- disassemble the bytecode\n"); - fprintf(stderr,"\tload -- load a source code file\n"); - fprintf(stderr,"\tlist (l) -- list the source code file\n"); - fprintf(stderr,"\trun (r) -- run the programm\n"); - fprintf(stderr,"\tbreak (b) -- add a breakpoint\n"); - fprintf(stderr,"\twatch (w) -- add a watchpoint\n"); - fprintf(stderr,"\tdelete (d) -- delete a breakpoint\n"); - fprintf(stderr,"\tcontinue (c) -- continue the program execution\n"); - fprintf(stderr,"\tnext (n) -- run the next instruction\n"); - fprintf(stderr,"\teval (e) -- run an instruction\n"); - fprintf(stderr,"\ttrace (t) -- trace the next instruction\n"); - fprintf(stderr,"\tprint (p) -- print the interpreter registers\n"); - fprintf(stderr,"\tstack (s) -- examine the stack\n"); - fprintf(stderr,"\tinfo -- print interpreter information\n"); - fprintf(stderr,"\tquit (q) -- exit the debugger\n"); - fprintf(stderr,"\thelp (h) -- print this help\n\n"); + PIO_eprintf(NULL, "\ +List of commands:\n\ + disassemble -- disassemble the bytecode\n\ + load -- load a source code file\n\ + list (l) -- list the source code file\n\ + run (r) -- run the program\n\ + break (b) -- add a breakpoint\n\ + watch (w) -- add a watchpoint\n\ + delete (d) -- delete a breakpoint\n\ + continue (c) -- continue the program execution\n\ + next (n) -- run the next instruction\n\ + eval (e) -- run an instruction\n\ + trace (t) -- trace the next instruction\n\ + print (p) -- print the interpreter registers\n\ + stack (s) -- examine the stack\n\ + info -- print interpreter information\n\ + quit (q) -- exit the debugger\n\ + help (h) -- print this help\n\n"); } /* diff --git a/debug.ops b/debug.ops index af848197a2..5174c78cb1 100644 --- a/debug.ops +++ b/debug.ops @@ -119,8 +119,8 @@ Print all the parrot registers at once. op debug_print() { if (!(interpreter->pdb->state & PDB_BREAK)) { - PDB_print_int(&interpreter->ctx.int_reg, -1); - PDB_print_num(&interpreter->ctx.num_reg, -1); + PDB_print_int(interpreter, &interpreter->ctx.int_reg, -1); + PDB_print_num(interpreter, &interpreter->ctx.num_reg, -1); PDB_print_string(interpreter,&interpreter->ctx.string_reg, -1); PDB_print_pmc(interpreter,&interpreter->ctx.pmc_reg, -1, NULL); } diff --git a/embed.c b/embed.c index 208711d391..2476f09dbb 100644 --- a/embed.c +++ b/embed.c @@ -36,9 +36,11 @@ Parrot_new(void) void Parrot_init(struct Parrot_Interp *interpreter, void* stacktop) +/* ^^^^^^^^^^^^^^ + XXX BD Do we really need this to be user-provided, or can + we set up our own in embed.c:Parrot_runcode()? +*/ { - /* This function currently unused, but is here in case we need it later. */ - if (!world_inited) { /* See comments in Parrot_new. */ world_inited = 1; @@ -97,13 +99,13 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) /* if we have stat(), get the actual file size so we can read it * in one chunk. */ if (stat(filename, &file_stat)) { - fprintf(stderr, "Parrot VM: Can't stat %s, code %i.\n", filename, + PIO_eprintf(interpreter, "Parrot VM: Can't stat %s, code %i.\n", filename, errno); return NULL; } if (!S_ISREG(file_stat.st_mode)) { - fprintf(stderr, "Parrot VM: %s is not a normal file.\n", filename); + PIO_eprintf(interpreter, "Parrot VM: %s is not a normal file.\n", filename); return NULL; } @@ -119,7 +121,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) #ifndef HAS_HEADER_SYSMMAN io = PIO_open(interpreter, filename, "<"); if (!io) { - fprintf(stderr, "Parrot VM: Can't open %s, code %i.\n", filename, + PIO_eprintf(interpreter, "Parrot VM: Can't open %s, code %i.\n", filename, errno); return NULL; } @@ -146,7 +148,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) if (NULL == program_code) { /* Whoops, out of memory. */ - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Could not allocate buffer to read packfile from PIO.\n"); return NULL; @@ -162,7 +164,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) realloc(program_code, program_size + chunk_size); if (NULL == program_code) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Could not reallocate buffer while reading packfile from PIO.\n"); return NULL; } @@ -171,7 +173,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) } if (read_result < 0) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Problem reading packfile from PIO.\n"); return NULL; } @@ -184,7 +186,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) fd = open(filename, O_RDONLY | O_BINARY); if (!fd) { - fprintf(stderr, "Parrot VM: Can't open %s, code %i.\n", filename, + PIO_eprintf(interpreter, "Parrot VM: Can't open %s, code %i.\n", filename, errno); return NULL; } @@ -193,14 +195,14 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) 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", + PIO_eprintf(interpreter, "Parrot VM: Can't read file %s, code %i.\n", filename, errno); return NULL; } #else /* HAS_HEADER_SYSMMAN */ - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: uncaught error occurred reading file or mmap not available.\n"); return NULL; @@ -214,7 +216,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) if (!PackFile_unpack (interpreter, pf, (opcode_t *)program_code, program_size)) { - fprintf(stderr, "Parrot VM: Can't unpack packfile %s.\n", filename); + PIO_eprintf(interpreter, "Parrot VM: Can't unpack packfile %s.\n", filename); return NULL; } @@ -236,14 +238,14 @@ Parrot_loadbc(struct Parrot_Interp *interpreter, struct PackFile *pf) interpreter->code = pf; } -void -Parrot_setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv) +static void +setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv) { - int i; + INTVAL i; PMC *userargv; if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "*** Parrot VM: Setting up ARGV array in P0. Current argc: %d ***\n", argc); } @@ -258,7 +260,7 @@ Parrot_setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv) 0, BUFFER_external_FLAG, 0); if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { - fprintf(stderr, "\t%d: %s\n", i, argv[i]); + PIO_eprintf(interpreter, "\t%vd: %s\n", i, argv[i]); } userargv->vtable->push_string(interpreter, userargv, arg); @@ -272,19 +274,19 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) /* Debugging mode nonsense. */ if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { - fprintf(stderr, "*** Parrot VM: Debugging enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Debugging enabled. ***\n"); if (Interp_flags_TEST(interpreter, PARROT_BOUNDS_FLAG)) { - fprintf(stderr, "*** Parrot VM: Bounds checking enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Bounds checking enabled. ***\n"); } if (Interp_flags_TEST(interpreter, PARROT_PREDEREF_FLAG)) { - fprintf(stderr, "*** Parrot VM: Predereferencing enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Predereferencing enabled. ***\n"); } if (Interp_flags_TEST(interpreter, PARROT_JIT_FLAG)) { - fprintf(stderr, "*** Parrot VM: JIT enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: JIT enabled. ***\n"); } if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) { - fprintf(stderr, "*** Parrot VM: Tracing enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Tracing enabled. ***\n"); } } @@ -293,7 +295,7 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) /* No JIT here--make sure they didn't ask for it. */ if (Interp_flags_TEST(interpreter, PARROT_JIT_FLAG)) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Platform " JIT_ARCHNAME " is not JIT-capable.\n"); exit(1); } @@ -303,7 +305,7 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) /* Set up @ARGS (or whatever this language calls it). XXX Should this be Array or PerlArray? */ - Parrot_setup_argv(interpreter, argc, argv); + setup_argv(interpreter, argc, argv); /* Let's kick the tires and light the fires--call interpreter.c:runops. */ runops(interpreter, interpreter->code, 0); @@ -313,15 +315,15 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) */ if (interpreter->profile != NULL) { - unsigned int j; - int op_count = 0; - int call_count = 0; + UINTVAL j; + UINTVAL op_count = 0; + UINTVAL call_count = 0; FLOATVAL sum_time = 0.0; - printf("\n\n"); - printf(" OPERATION PROFILE \n\n"); - printf(" CODE OP FULL NAME CALLS TOTAL TIME AVG TIME\n"); - printf(" ----- ------------ ------ ---------- ----------\n"); + PIO_printf(interpreter, "\n\n"); + PIO_printf(interpreter, " OPERATION PROFILE \n\n"); + PIO_printf(interpreter, " CODE OP FULL NAME CALLS TOTAL TIME AVG TIME\n"); + PIO_printf(interpreter, " ----- ------------ ------ ---------- ----------\n"); for (j = 0; j < interpreter->op_count; j++) { if (interpreter->profile[j].numcalls > 0) { @@ -329,41 +331,41 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) call_count += interpreter->profile[j].numcalls; sum_time += interpreter->profile[j].time; - printf(" %5u %-12s %6ld %10f %10f\n", j, + PIO_printf(interpreter, " %5vu %-12s %6vu %10vf %10vf\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 + (FLOATVAL)(interpreter->profile[j].time / + (FLOATVAL)interpreter->profile[j].numcalls) ); } } - printf(" ----- ------------ ------ ---------- ----------\n"); - printf(" %5d %-12s %6d %10f %10f\n", + PIO_printf(interpreter, " ----- ------------ ------ ---------- ----------\n"); + PIO_printf(interpreter, " %5vu %-12s %6vu %10vf %10vf\n", op_count, "", call_count, sum_time, - sum_time / (FLOATVAL)call_count + (FLOATVAL)(sum_time / (FLOATVAL)call_count) ); } if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { /* Give the souls brave enough to activate debugging an earful * about GC. */ - fprintf(stderr, "\ + PIO_eprintf(interpreter, "\ *** Parrot VM: Dumping GC info ***\n\ -\tTotal memory allocated: %u\n\ -\tTotal DOD runs: %u\n\ -\tTotal collector runs: %u\n\ -\tActive PMCs: %u\n\ -\tActive buffers: %u\n\ -\tTotal PMCs: %u\n\ -\tTotal buffers: %u\n\ +\tTotal memory allocated: %p\n\ +\tTotal DOD runs: %p\n\ +\tTotal collector runs: %p\n\ +\tActive PMCs: %p\n\ +\tActive buffers: %p\n\ +\tTotal PMCs: %p\n\ +\tTotal buffers: %p\n\ \tSince last collection:\n\ -\t\tHeader allocations: %u\n\ -\t\tMemory allocations: %u\n\ +\t\tHeader allocations: %p\n\ +\t\tMemory allocations: %p\n\ \n", interpreter->memory_allocated, interpreter->dod_runs, @@ -382,7 +384,7 @@ void Parrot_destroy(struct Parrot_Interp *interp) { /* XXX Leaks tons of memory. */ - free(interp); + mem_sys_free(interp); } /* XXX Doesn't handle arguments with spaces */ @@ -448,11 +450,11 @@ Parrot_disassemble(struct Parrot_Interp *interpreter) while (line->next) { /* If it has a label print it */ if (line->label) - printf("L%li:\t", line->label->number); + PIO_printf(interpreter, "L%li:\t", line->label->number); c = pdb->file->source + line->source_offset; while (*c != '\n' && c) - printf("%c", *(c++)); - printf("\n"); + PIO_printf(interpreter, "%c", *(c++)); + PIO_printf(interpreter, "\n"); line = line->next; } return; diff --git a/exceptions.c b/exceptions.c index 9b2cfecbdb..b530651da7 100644 --- a/exceptions.c +++ b/exceptions.c @@ -28,35 +28,48 @@ internal_exception(int exitcode, const char *format, ...) /* Panic handler */ -#define dumpcore() printf("Sorry, coredump is not yet implemented for this platform.\n\n"); exit(1); +#define dumpcore() PIO_printf(interpreter, "Sorry, coredump is not yet implemented for this platform.\n\n"); exit(1); void do_panic(struct Parrot_Interp *interpreter, const char *message, const char *file, int line) { - printf("Parrot VM: PANIC: %s!\n", message ? message : "(no message available)"); - printf("C file %s, line %d\n", file ? file : "(file name not available)", line); - printf("Parrot file %s, ", "(not available)"); - if (interpreter) - printf("line %d\n", interpreter->current_line); - else - printf("line ((not available)\n"); - printf("\n\ + /* Note: we can't format any floats in here--Parrot_sprintf + ** may panic because of floats. + */ + + PIO_printf(interpreter, "\ +Parrot VM: PANIC: %s!\n\ +C file %s, line %d\n\ +Parrot file %s, line %d\n\ +\n\ We highly suggest you notify the Parrot team if you have not been working on \n\ Parrot. Use bugs6.perl.org or send an e-mail to perl6-internals@perl.org. \n\ Include the entire text of this error message and the text of the script that \n\ generated the error. If you've made any modifications to Parrot, please \n\ -describe them as well.\n"); - printf("Version : %s\n", PARROT_VERSION); - printf("Configured : %s\n", PARROT_CONFIG_DATE); - printf("Architecture: %s\n", PARROT_ARCHNAME); - printf("JIT Capable : %s\n", (JIT_CAPABLE ? "Yes" : "No")); - if (interpreter) - printf("Interp Flags: 0x%x\n", interpreter->flags); - else - printf("Interp Flags: (not available)\n"); - printf("Exceptions : (missing from core)\n"); - printf("\nDumping core...\n\n"); +describe them as well.\n\ +\n\ +Version : %s\n\ +Configured : %s\n\ +Architecture: %s\n\ +JIT Capable : %s\n\ +Interp Flags: %#x\n\ +Exceptions : %s\n\ +\n\ +Dumping Core...\n", + message ? message : "(not available)", + line, + file ? file : "(not available)", + interpreter ? string_to_cstring(interpreter, interpreter->current_file) : "(not available)", + interpreter ? (int)interpreter->current_line : 0, + PARROT_VERSION, + PARROT_CONFIG_DATE, + PARROT_ARCHNAME, + JIT_CAPABLE ? "Yes" : "No", + interpreter ? interpreter->flags : -1, + "(missing from core)" + ); + dumpcore(); } diff --git a/hash.c b/hash.c index 2b4e3270ba..39eb80c108 100644 --- a/hash.c +++ b/hash.c @@ -104,7 +104,8 @@ void dump_hash(Interp *interpreter, HASH *hash) { HashIndex i; - fprintf(stderr, "Hashtable[" INTVAL_FMT "/" INTVAL_FMT "]\n", + PIO_fprintf(interpreter, PIO_STDERR(interpreter), + "Hashtable[%vd/%vd]\n", hash->entries, hash->max_chain + 1); /* Iterate one past the end of the hashtable, so we can use the @@ -115,13 +116,13 @@ dump_hash(Interp *interpreter, HASH *hash) if (i > hash->max_chain) bucket = getBucket(hash, hash->free_list); else bucket = lookupBucket(hash, i); if (bucket == NULL) continue; - fprintf(stderr, " Bucket " INTVAL_FMT ": ", i); + PIO_eprintf(interpreter, " Bucket %vd: ", i); while (bucket) { - fprintf(stderr, "type(%d)", bucket->value.type); + PIO_eprintf(interpreter, "type(%d)", bucket->value.type); bucket = getBucket(hash, bucket->next); - if (bucket) fprintf(stderr, " -> "); + if (bucket) PIO_eprintf(interpreter, " -> "); } - fprintf(stderr, "\n"); + PIO_eprintf(interpreter, "\n"); } } @@ -335,7 +336,7 @@ hash_size(Interp *interpreter, HASH *hash) return hash->entries; } else { - fprintf(stderr, "*** hash_size asked to check a NULL hash\n"); + PIO_eprintf(interpreter, "*** hash_size asked to check a NULL hash\n"); return 0; } } diff --git a/include/parrot/debug.h b/include/parrot/debug.h index cfb20d43ae..9265104859 100644 --- a/include/parrot/debug.h +++ b/include/parrot/debug.h @@ -155,9 +155,9 @@ void PDB_get_command(struct Parrot_Interp *interpreter); void PDB_print(struct Parrot_Interp *interpreter, const char *command); -void PDB_print_int(struct IReg *int_reg, int regnum); +void PDB_print_int(struct Parrot_Interp *interpreter, struct IReg *int_reg, int regnum); -void PDB_print_num(struct NReg *num_reg, int regnum); +void PDB_print_num(struct Parrot_Interp *interpreter, struct NReg *num_reg, int regnum); void PDB_print_string(struct Parrot_Interp *interpreter, struct SReg *string_reg, int regnum); diff --git a/include/parrot/io.h b/include/parrot/io.h index acccd80654..8805d62a19 100644 --- a/include/parrot/io.h +++ b/include/parrot/io.h @@ -322,6 +322,11 @@ extern INTVAL PIO_seek(theINTERP, ParrotIO *, INTVAL hi, INTVAL lo, INTVAL whence); extern INTVAL PIO_eof(theINTERP, ParrotIO *); +extern INTVAL PIO_putps(theINTERP, ParrotIO *io, STRING *s); +extern INTVAL PIO_fprintf(theINTERP, ParrotIO *io, const char *s, ...); +extern INTVAL PIO_printf(theINTERP, const char *s, ...); +extern INTVAL PIO_eprintf(theINTERP, const char *s, ...); + /* Put platform specific macros here if you must */ #ifdef PIO_OS_WIN32 diff --git a/include/parrot/misc.h b/include/parrot/misc.h index 609423b5e0..f6408fbf0b 100644 --- a/include/parrot/misc.h +++ b/include/parrot/misc.h @@ -1,18 +1,37 @@ +/* misc.h + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id$ + * Overview: + * Miscellaneous functions, mainly the Parrot_sprintf family + * Data Structure and Algorithms: + * Uses a generalized formatting algorithm (spf_render.c) with + * a specialized vtable (spf_vtable.c) to handle argument extraction. + * History: + * This file used to be a simple one, with just a few function prototypes + * in it. When misc.c was split in three, this file took on the job of + * being the internal header as well. + * To expose the guts of Parrot_sprintf, define IN_SPF_SYSTEM before + * including this file. + * Notes: + * References: misc.c, spf_vtable.c, spf_render.c + */ + #if !defined(PARROT_MISC_H_GUARD) #define PARROT_MISC_H_GUARD #include "parrot/parrot.h" #include -STRING *Parrot_vsprintf_s(struct Parrot_Interp *, STRING *pat, va_list *); +STRING *Parrot_vsprintf_s(struct Parrot_Interp *, STRING *pat, va_list); -STRING *Parrot_vsprintf_c(struct Parrot_Interp *, const char *pat, va_list *); +STRING *Parrot_vsprintf_c(struct Parrot_Interp *, const char *pat, va_list); void Parrot_vsprintf(struct Parrot_Interp *, char *targ, const char *pat, - va_list *); + va_list); -void Parrot_vsnprintf(struct Parrot_Interp *, char *targ, UINTVAL len, - const char *pat, va_list *); +void Parrot_vsnprintf(struct Parrot_Interp *, char *targ, size_t len, + const char *pat, va_list); STRING *Parrot_sprintf_s(struct Parrot_Interp *, STRING *pat, ...); @@ -20,9 +39,104 @@ STRING *Parrot_sprintf_c(struct Parrot_Interp *, const char *pat, ...); void Parrot_sprintf(struct Parrot_Interp *, char *targ, const char *pat, ...); -void Parrot_snprintf(struct Parrot_Interp *, char *targ, UINTVAL len, +void Parrot_snprintf(struct Parrot_Interp *, char *targ, size_t len, const char *pat, ...); +STRING *Parrot_psprintf(struct Parrot_Interp *interpreter, STRING *pat, + PMC * ary); + + +#ifdef IN_SPF_SYSTEM + + /* The size of all our buffers (and the maximum width of a float + * field). + */ +# define PARROT_SPRINTF_BUFFER_SIZE 4096 + + /* The maximum floating-point precision--hopefully this and the + * width cap will help head off buffer overruns. + */ +# define PARROT_SPRINTF_MAX_PREC 3 * PARROT_SPRINTF_BUFFER_SIZE / 4 + +# define cstr2pstr(cstr) string_make(interpreter, cstr, strlen(cstr), NULL, 0, NULL) +# define char2pstr(ch) string_make(interpreter, &ch , 1, NULL, 0, NULL) + + /* SPRINTF DATA STRUCTURE AND FLAGS */ + + typedef enum spf_phase_t { + PHASE_FLAGS = 0, + PHASE_WIDTH, + PHASE_PREC, + PHASE_TYPE, + PHASE_TERM, + PHASE_DONE + } PHASE; + + typedef enum spf_flag_t { + FLAG_MINUS = 1, + FLAG_PLUS = 2, + FLAG_ZERO = 4, + FLAG_SPACE = 8, + FLAG_SHARP = 16, + FLAG_WIDTH = 32, + FLAG_PREC = 64 + } FLAG; + + typedef enum spf_type_t { + SIZE_REG = 0, + SIZE_SHORT, + SIZE_LONG, + SIZE_HUGE, + SIZE_XVAL, + SIZE_OPCODE, + SIZE_PMC, + SIZE_PSTR + } TYPE; + + typedef struct spfinfo_t { + UINTVAL width; + UINTVAL prec; + FLAG flags; + TYPE type; + PHASE phase; + } *SpfInfo; + + /* SPRINTF ARGUMENT OBJECT */ + + typedef struct sprintf_obj SPRINTF_OBJ; + + typedef STRING *(*sprintf_getchar_t) (struct Parrot_Interp *, INTVAL, + SPRINTF_OBJ *); + typedef HUGEINTVAL(*sprintf_getint_t) (struct Parrot_Interp *, INTVAL, + SPRINTF_OBJ *); + typedef UHUGEINTVAL(*sprintf_getuint_t) (struct Parrot_Interp *, INTVAL, + SPRINTF_OBJ *); + typedef HUGEFLOATVAL(*sprintf_getfloat_t) (struct Parrot_Interp *, INTVAL, + SPRINTF_OBJ *); + typedef STRING *(*sprintf_getstring_t) (struct Parrot_Interp *, INTVAL, + SPRINTF_OBJ *); + typedef void *(*sprintf_getptr_t) (struct Parrot_Interp *, INTVAL, + SPRINTF_OBJ *); + + struct sprintf_obj { + void *data; + INTVAL index; + + sprintf_getchar_t getchr; + sprintf_getint_t getint; + sprintf_getuint_t getuint; + sprintf_getfloat_t getfloat; + sprintf_getstring_t getstring; + sprintf_getptr_t getptr; + }; + + extern SPRINTF_OBJ pmc_core; + extern SPRINTF_OBJ va_core; + + STRING *Parrot_sprintf_format(struct Parrot_Interp *interpreter, + STRING *pat, SPRINTF_OBJ * obj); + +#endif #endif diff --git a/include/parrot/string_funcs.h b/include/parrot/string_funcs.h index 0109099417..a270d661a7 100644 --- a/include/parrot/string_funcs.h +++ b/include/parrot/string_funcs.h @@ -30,6 +30,7 @@ STRING *string_replace(struct Parrot_Interp *, STRING *, INTVAL, INTVAL, INTVAL string_compare(struct Parrot_Interp *, STRING *, STRING *); INTVAL string_bool(const STRING *); const char *Parrot_string_cstring(const STRING *); +STRING *string_set(struct Parrot_Interp *, STRING *, STRING *); /* Declarations of other functions */ UINTVAL string_length(const STRING *); diff --git a/interpreter.c b/interpreter.c index 4bd9590e94..cbccba6215 100644 --- a/interpreter.c +++ b/interpreter.c @@ -22,8 +22,6 @@ # include "parrot/oplib/core_ops_cg.h" #endif - - /*=for api interpreter runops_generic * TODO: Not really part of the API, but here's the docs. * Generic runops, which takes a function pointer for the core. diff --git a/io/io.c b/io/io.c index 11d1f288a2..6c65a4f6e5 100644 --- a/io/io.c +++ b/io/io.c @@ -21,6 +21,7 @@ #include "parrot/parrot.h" +#include /* This is list of valid layers */ ParrotIOLayer *pio_registered_layers; @@ -362,6 +363,7 @@ PIO_copy_stack(ParrotIOLayer *stack) * Parse string for file open mode and return generic * bits. The low level OS layers may then interpret the * generic bits differently depending on platform. + * XXX BD Should this be static? */ INTVAL PIO_parse_open_flags(const char *flagstr) @@ -588,8 +590,8 @@ PIO_eof(theINTERP, ParrotIO *io) } -/* Don't use this on a standard Parrot string, unless you - * have null terminated it. +/* Don't use this on a standard Parrot string--that's what + * PIO_putps is for. */ INTVAL PIO_puts(theINTERP, ParrotIO *io, const char *s) @@ -607,6 +609,74 @@ PIO_puts(theINTERP, ParrotIO *io, const char *s) return -1; } +INTVAL +PIO_putps(theINTERP, ParrotIO *io, STRING *s) { + return PIO_puts(interpreter, io, string_to_cstring(interpreter, s)); +} + +INTVAL +PIO_fprintf(theINTERP, ParrotIO *io, const char *s, ...) { + va_list args; + INTVAL ret=-1; + + va_start(args, s); + + ret=PIO_putps(interpreter, io, Parrot_vsprintf_c(interpreter, s, args)); + + va_end(args); + + return ret; +} + +INTVAL +PIO_printf(theINTERP, const char *s, ...) { + va_list args; + STRING *str; + INTVAL ret=-1; + + va_start(args, s); + + str=Parrot_vsprintf_c(interpreter, s, args); + + if(interpreter) { + ret=PIO_putps(interpreter, PIO_STDOUT(interpreter), str); + } + else { + /* Be nice about this... + ** XXX BD Should this use the default PIO_STDOUT or something? + */ + ret=printf("%s", string_to_cstring(interpreter, str)); + } + + va_end(args); + + return ret; +} + +INTVAL +PIO_eprintf(theINTERP, const char *s, ...) { + va_list args; + STRING *str; + INTVAL ret=-1; + + va_start(args, s); + + str=Parrot_vsprintf_c(interpreter, s, args); + + if(interpreter) { + ret=PIO_putps(interpreter, PIO_STDERR(interpreter), str); + } + else { + /* Be nice about this... + ** XXX BD Should this use the default PIO_STDERR or something? + */ + ret=fprintf(stderr, "%s", string_to_cstring(interpreter, str)); + } + + va_end(args); + + return ret; +} /* * Local variables: diff --git a/jit.c b/jit.c index 0b5b843939..0109ef46dc 100644 --- a/jit.c +++ b/jit.c @@ -376,36 +376,36 @@ END_SECTION:cur_section->end = cur_op; #if JIT_DEBUG cur_section = optimizer->sections; while (cur_section) { - fprintf(stderr, "\nSection:\n"); - fprintf(stderr, "%s\n", (cur_section->type) ? "JITTED" : "NOT JITTED"); - fprintf(stderr, "\tbegin:\t0x%x\t(%li)\n", - (unsigned int)cur_section->begin, *cur_section->begin); - fprintf(stderr, "\tend:\t0x%x\t(%li)\n", - (unsigned int)cur_section->end, *cur_section->end); - fprintf(stderr, "\tInt register count:\t"); + PIO_eprintf(interpreter, "\nSection:\n"); + PIO_eprintf(interpreter, "%s\n", (cur_section->type) ? "JITTED" : "NOT JITTED"); + PIO_eprintf(interpreter, "\tbegin:\t%#p\t(%Ou)\n", + cur_section->begin, *cur_section->begin); + PIO_eprintf(interpreter, "\tend:\t%#p\t(%Ou)\n", + cur_section->end, *cur_section->end); + PIO_eprintf(interpreter, "\tInt register count:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->int_reg_count[i]); - fprintf(stderr, "\n\tInt register usage:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->int_reg_count[i]); + PIO_eprintf(interpreter, "\n\tInt register usage:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->int_reg_usage[i]); - fprintf(stderr, "\n\tInt register direction:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->int_reg_usage[i]); + PIO_eprintf(interpreter, "\n\tInt register direction:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", (int)cur_section->int_reg_dir[i]); - fprintf(stderr, "\n\tInt registers used:\t%i\n", + PIO_eprintf(interpreter, "%i ", (int)cur_section->int_reg_dir[i]); + PIO_eprintf(interpreter, "\n\tInt registers used:\t%i\n", cur_section->int_registers_used); - fprintf(stderr, "\tFloat register count:\t"); + PIO_eprintf(interpreter, "\tFloat register count:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->float_reg_count[i]); - fprintf(stderr, "\n\tFloat register usage:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->float_reg_count[i]); + PIO_eprintf(interpreter, "\n\tFloat register usage:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->float_reg_usage[i]); - fprintf(stderr, "\n\tFloat register direction:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->float_reg_usage[i]); + PIO_eprintf(interpreter, "\n\tFloat register direction:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", (int)cur_section->float_reg_dir[i]); - fprintf(stderr, "\n\tFloat Registers used:\t%i\n", + PIO_eprintf(interpreter, "%i ", (int)cur_section->float_reg_dir[i]); + PIO_eprintf(interpreter, "\n\tFloat Registers used:\t%i\n", cur_section->float_registers_used); - fprintf(stderr, "\tJit opcodes:\t%i\n", cur_section->jit_op_count); - fprintf(stderr, "\tTotal opcodes:\t%i\n", cur_section->op_count); + PIO_eprintf(interpreter, "\tJit opcodes:\t%u\n", cur_section->jit_op_count); + PIO_eprintf(interpreter, "\tTotal opcodes:\t%u\n", cur_section->op_count); cur_section = cur_section->next; } #endif diff --git a/malloc.c b/malloc.c index ca9ca25f34..44e0e0a5e5 100644 --- a/malloc.c +++ b/malloc.c @@ -4703,30 +4703,30 @@ void mSTATs() { CHUNK_SIZE_T free, reserved, committed; vminfo (&free, &reserved, &committed); - fprintf(stderr, "free bytes = %10lu\n", + PIO_eprintf(NULL, "free bytes = %10lu\n", free); - fprintf(stderr, "reserved bytes = %10lu\n", + PIO_eprintf(NULL, "reserved bytes = %10lu\n", reserved); - fprintf(stderr, "committed bytes = %10lu\n", + PIO_eprintf(NULL, "committed bytes = %10lu\n", committed); } #endif - fprintf(stderr, "max system bytes = %10lu\n", + PIO_eprintf(NULL, "max system bytes = %10lu\n", (CHUNK_SIZE_T)(mi.usmblks)); - fprintf(stderr, "system bytes = %10lu\n", + PIO_eprintf(NULL, "system bytes = %10lu\n", (CHUNK_SIZE_T)(mi.arena + mi.hblkhd)); - fprintf(stderr, "in use bytes = %10lu\n", + PIO_eprintf(NULL, "in use bytes = %10lu\n", (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd)); #ifdef WIN32 { CHUNK_SIZE_T kernel, user; if (cpuinfo (TRUE, &kernel, &user)) { - fprintf(stderr, "kernel ms = %10lu\n", + PIO_eprintf(NULL, "kernel ms = %10lu\n", kernel); - fprintf(stderr, "user ms = %10lu\n", + PIO_eprintf(NULL, "user ms = %10lu\n", user); } } @@ -5033,7 +5033,7 @@ static void *sbrk (long size) { static region_list_entry *g_last; void *result = (void *) MORECORE_FAILURE; #ifdef TRACE - printf ("sbrk %d\n", size); + PIO_printf (NULL, "sbrk %d\n", size); #endif #if defined (USE_MALLOC_LOCK) && defined (NEEDED) /* Wait for spin lock */ @@ -5090,7 +5090,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) base_committed % g_pagesize == 0); #ifdef TRACE - printf ("Commit %p %d\n", base_committed, remaining_commit_size); + PIO_printf (NULL, "Commit %p %d\n", base_committed, remaining_commit_size); #endif /* Adjust the regions commit top */ g_last->top_committed = (char *) base_committed + remaining_commit_size; @@ -5116,7 +5116,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0); #ifdef TRACE - printf ("Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize, + PIO_printf (NULL, "Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize, memory_info.State == MEM_FREE ? "FREE": (memory_info.State == MEM_RESERVE ? "RESERVED": (memory_info.State == MEM_COMMIT ? "COMMITTED": "?"))); @@ -5160,7 +5160,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) base_reserved % g_regionsize == 0); #ifdef TRACE - printf ("Reserve %p %d\n", base_reserved, reserve_size); + PIO_printf (NULL, "Reserve %p %d\n", base_reserved, reserve_size); #endif /* Did we get contiguous memory? */ if (contiguous) { @@ -5198,7 +5198,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) base_committed % g_pagesize == 0); #ifdef TRACE - printf ("Commit %p %d\n", base_committed, commit_size); + PIO_printf (NULL, "Commit %p %d\n", base_committed, commit_size); #endif /* Adjust the regions commit top */ g_last->top_committed = (char *) base_committed + commit_size; @@ -5226,7 +5226,7 @@ static void *sbrk (long size) { if (! rc) goto sbrk_exit; #ifdef TRACE - printf ("Release %p %d\n", base_reserved, release_size); + PIO_printf (NULL, "Release %p %d\n", base_reserved, release_size); #endif } /* Adjust deallocation size */ @@ -5252,7 +5252,7 @@ static void *sbrk (long size) { if (! rc) goto sbrk_exit; #ifdef TRACE - printf ("Decommit %p %d\n", base_committed, decommit_size); + PIO_printf (NULL, "Decommit %p %d\n", base_committed, decommit_size); #endif } /* Adjust deallocation size and regions commit and allocate top */ @@ -5295,7 +5295,7 @@ static void *mmap (void *ptr, long size, long prot, long type, long handle, long static long g_pagesize; static long g_regionsize; #ifdef TRACE - printf ("mmap %d\n", size); + PIO_printf (NULL, "mmap %d\n", size); #endif #if defined (USE_MALLOC_LOCK) && defined (NEEDED) /* Wait for spin lock */ @@ -5319,7 +5319,7 @@ static void *mmap (void *ptr, long size, long prot, long type, long handle, long /* Assert postconditions */ assert ((unsigned) ptr % g_regionsize == 0); #ifdef TRACE - printf ("Commit %p %d\n", ptr, size); + PIO_printf (NULL, "Commit %p %d\n", ptr, size); #endif mmap_exit: #if defined (USE_MALLOC_LOCK) && defined (NEEDED) @@ -5335,7 +5335,7 @@ static long munmap (void *ptr, long size) { static long g_regionsize; int rc = MUNMAP_FAILURE; #ifdef TRACE - printf ("munmap %p %d\n", ptr, size); + PIO_printf (NULL, "munmap %p %d\n", ptr, size); #endif #if defined (USE_MALLOC_LOCK) && defined (NEEDED) /* Wait for spin lock */ @@ -5355,7 +5355,7 @@ static long munmap (void *ptr, long size) { goto munmap_exit; rc = 0; #ifdef TRACE - printf ("Release %p %d\n", ptr, size); + PIO_printf (NULL, "Release %p %d\n", ptr, size); #endif munmap_exit: #if defined (USE_MALLOC_LOCK) && defined (NEEDED) diff --git a/misc.c b/misc.c index 4fd107f7e5..223fe673e9 100644 --- a/misc.c +++ b/misc.c @@ -3,493 +3,46 @@ * CVS Info * $Id$ * Overview: - * Miscellaneous functions + * Miscellaneous functions, mainly the Parrot_sprintf family * Data Structure and Algorithms: + * Uses a generalized formatting algorithm (spf_render.c) with + * a specialized vtable (spf_vtable.c) to handle argument extraction. * History: + * This was once a simple, vararg-based implementation that existed + * completely within this file. When the file grew to be nearly 1,000 + * lines long, I split it into three. --BD * Notes: - * References: + * References: misc.h, spf_vtable.c, spf_render.c */ -#include "parrot/parrot.h" - -#include - -typedef long HUGEINTVAL; -typedef unsigned long UHUGEINTVAL; - -typedef struct spfinfo_t { - UINTVAL flags; - UINTVAL width; - UINTVAL prec; - UINTVAL type; - UINTVAL phase; -} *SpfInfo; - -#define cstr2pstr(cstr) string_make(interpreter, cstr, strlen(cstr), NULL, 0, NULL) -#define char2pstr(ch) string_make(interpreter, &ch, 1, NULL, 0, NULL) - -#define PHASE_FLAGS 0 -#define PHASE_WIDTH 1 -#define PHASE_PREC 2 -#define PHASE_TYPE 3 -#define PHASE_TERM 4 -#define PHASE_DONE 5 - -#define FLAG_MINUS 1 -#define FLAG_PLUS 2 -#define FLAG_ZERO 4 -#define FLAG_SPACE 8 -#define FLAG_SHARP 16 - -#define SIZE_REG 0 -#define SIZE_SHORT 1 -#define SIZE_LONG 2 -#define SIZE_HUGE 3 -#define SIZE_XVAL 4 - -#define GetInt(targ, whichone) \ - switch(whichone) { \ - case SIZE_REG: \ - targ=(HUGEINTVAL)(int)va_arg(*args, int); \ - break; \ - case SIZE_SHORT: /* "'short int' is promoted to 'int' when passed through '...'" */ \ - targ=(HUGEINTVAL)(short)va_arg(*args, int); \ - break; \ - case SIZE_LONG: \ - targ=(HUGEINTVAL)(long)va_arg(*args, long); \ - break; \ - case SIZE_HUGE: \ - targ=(HUGEINTVAL)(long /*long*/)va_arg(*args, long /*long*/); \ - break; \ - case SIZE_XVAL: \ - targ=(HUGEINTVAL)(INTVAL)va_arg(*args, INTVAL); \ - break; \ - } - -#define GetUInt(targ, whichone) \ - switch(whichone) { \ - case SIZE_REG: \ - targ=(UHUGEINTVAL)(unsigned int)va_arg(*args, unsigned int); \ - break; \ - case SIZE_SHORT: /* short int promoted HLAGHLAGHLAGH. See note above */ \ - targ=(UHUGEINTVAL)(unsigned short)va_arg(*args, int); \ - break; \ - case SIZE_LONG: \ - targ=(UHUGEINTVAL)(unsigned long)va_arg(*args, unsigned long); \ - break; \ - case SIZE_HUGE: \ - targ=(UHUGEINTVAL)(unsigned long /*long*/)va_arg(*args, unsigned long /*long*/); \ - break; \ - case SIZE_XVAL: \ - targ=(UHUGEINTVAL)(UINTVAL)va_arg(*args, UINTVAL); \ - break; \ - } - -/* -void int_to_str(char *, char *, HUGEINTVAL, INTVAL ); -*/ - -void gen_sprintf_call(char *, char *, SpfInfo, char); - -static void -uint_to_str(char *buf1, char *buf2, UHUGEINTVAL num, char base) -{ - int i = 0, cur2; - char cur; - - do { - cur = (char)(num % base); - - if (cur < 10) { - buf2[i] = (char)('0' + cur); - } - else { - buf2[i] = (char)('a' + cur - 10); - } - - i++; - } while (num /= base); - - cur2 = i; - - for (i = 0; i <= cur2; i++) { - buf1[i] = buf2[cur2 - i]; - } -} - -static void -int_to_str(char *buf1, char *buf2, HUGEINTVAL num, char base) -{ - INTVAL neg; - int i = 0, cur2; - char cur; - - if (num < 0) { - neg = 1; - num = -num; - } - else { - neg = 0; - } - - do { - cur = (char)(num % base); - - if (cur < 10) { - buf2[i] = (char)('0' + cur); - } - else { - buf2[i] = (char)('a' + cur - 10); - } - - i++; - } while (num /= base); - - if (neg) { - buf2[i++] = '-'; - } - - cur2 = i; - - for (i = 0; i < cur2; i++) { - buf1[i] = buf2[cur2 - i - 1]; - } +#define IN_SPF_SYSTEM - buf1[i] = 0; -} - -static void -Pad_it(SpfInfo info, char *buf) -{ - int i; - int len = strlen(buf); - int howmuch = info->width - len; - - if (!info->width || howmuch == 0) { - return; - } - else if (howmuch < 0) { - memmove(buf, buf - howmuch, (size_t)(len + howmuch)); - } - else if (info->flags & FLAG_MINUS) { /* left-align */ - for (i = 0; i < howmuch; i++) { - buf[i + len] = ' '; - } - - buf[i + len] = 0; - } - else { /* right-align */ - memmove(buf + howmuch, buf, (size_t)len); - - for (i = 0; i < howmuch; i++) { - buf[i] = ' '; - } - } -} - -void -gen_sprintf_call(char *buf, char *buf2, SpfInfo info, char thingy) -{ - int i = 0; - buf[i++] = '%'; - - if (info->flags) { - if (info->flags & FLAG_MINUS) { - buf[i++] = '-'; - } - if (info->flags & FLAG_PLUS) { - buf[i++] = '+'; - } - if (info->flags & FLAG_ZERO) { - buf[i++] = '0'; - } - if (info->flags & FLAG_SPACE) { - buf[i++] = ' '; - } - if (info->flags & FLAG_SHARP) { - buf[i++] = '#'; - } - } - - if (info->width) { - uint_to_str(buf + i, buf2, info->width, 10); - i = strlen(buf); - } - - if (info->prec) { - buf[i++] = '.'; - uint_to_str(buf + i, buf2, info->prec, 10); - i = strlen(buf); - } +#include "parrot/parrot.h" - buf[i++] = thingy; - buf[i] = 0; -} +/* All the other sprintf variants are implemented in terms of + * Parrot_vsprintf_s. + * + * NAMING CONVENTION: + * Parrot_v?n?sprintf - a (nearly) drop-in replacement for v?n?sprintf. + * Parrot_v?sprintf_c - takes a C-string format, returns a Parrot string. + * Parrot_v?sprintf_s - takes a Parrot string format, returns a Parrot string. + * + * So the _ means "returns Parrot string" and the other letter indicates the + * type for the format. :^) + */ STRING * -Parrot_vsprintf_s(struct Parrot_Interp *interpreter, STRING *pat, - va_list *args) +Parrot_vsprintf_s(struct Parrot_Interp *interpreter, STRING *pat, va_list args) { - INTVAL i; - STRING *targ = NULL; - register char *t1 = mem_sys_allocate(4096); - register char *t2 = mem_sys_allocate(4096); - - for (i = 0; i < (INTVAL)string_length(pat); i++) { - if (string_ord(pat, i) == '%') { - if (string_ord(pat, i + 1) == '%') { - i++; - } - else { - /* hoo boy, here we go... */ - char *chptr; - STRING *string; - PMC *pmc; - double dbl; - register HUGEINTVAL theint = 0; - register UHUGEINTVAL theuint = 0; - - struct spfinfo_t info = { 0, 0, 0, 0, 0 }; - - for (i++; i < (INTVAL)string_length(pat) - && info.phase != PHASE_DONE; i++) { - INTVAL ch = string_ord(pat, i); - - switch (info.phase) { - /*@fallthrough@ */ case PHASE_FLAGS: - switch (ch) { - case '-': - info.flags |= FLAG_MINUS; - break; - - case '+': - info.flags |= FLAG_PLUS; - break; - - case '0': - info.flags |= FLAG_ZERO; - break; - - case ' ': - info.flags |= FLAG_SPACE; - break; - - case '#': - info.flags |= FLAG_SHARP; - break; - - default: - info.phase = PHASE_WIDTH; - } - - - /*@fallthrough@ */ case PHASE_WIDTH: - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '8': - case '9': - info.width *= 10; - info.width += ch - '0'; - break; - - case '.': - info.phase = PHASE_PREC; - continue; - - default: - info.phase = PHASE_PREC; - } - - /*@fallthrough@ */ case PHASE_PREC: - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '8': - case '9': - info.prec *= 10; - info.prec += ch - '0'; - continue; - - default: - info.phase = PHASE_TYPE; - } - - /*@fallthrough@ */ case PHASE_TYPE: - switch (ch) { - case 'h': - info.type = SIZE_SHORT; - continue; - - case 'l': - info.type = SIZE_LONG; - continue; - - case 'H': - info.type = SIZE_HUGE; - continue; - - case 'v': - info.type = SIZE_XVAL; - continue; - - default: - info.phase = PHASE_TERM; - } - - - /*@fallthrough@ */ case PHASE_TERM: - switch (ch) { - /* INTEGERS */ - case 'c': - targ = string_concat(interpreter, targ, - char2pstr(ch), 0); - break; - - case 'd': - case 'i': - GetInt(theint, info.type); - int_to_str(t1, t2, theint, 10); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'o': - GetInt(theint, info.type); - int_to_str(t1, t2, theint, 8); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'x': - GetInt(theint, info.type); - int_to_str(t1, t2, theint, 16); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'u': - GetUInt(theuint, info.type); - uint_to_str(t1, t2, theuint, 10); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'p': - chptr = va_arg(*args, void *); - int_to_str(t1, t2, (HUGEINTVAL)chptr, 16); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - /* FLOATS - We cheat on these and use the system sprintf. */ - case 'e': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'e'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'E': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'E'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'f': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'f'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'g': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'g'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'G': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'G'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - /* STRINGS */ - case 's': - chptr = va_arg(*args, char *); - if (info.prec) - targ = string_concat(interpreter, targ, - string_make(interpreter, chptr, - info.prec, NULL,0,NULL),0); - else - targ = string_concat(interpreter, targ, - cstr2pstr(chptr), 0); - break; - - case 'S': - string = va_arg(*args, STRING *); - if (info.prec) - targ = string_concat(interpreter, targ, - string_chopn(string, -info.prec), 0); - else - targ = string_concat(interpreter, targ, string, 0); - break; - - case 'P': - pmc = va_arg(*args, PMC *); - targ = - string_concat(interpreter, targ, - string_chopn( - pmc->vtable->get_string(interpreter, pmc), - -info.prec), - 0); - break; - - } - - info.phase = PHASE_DONE; - } - } - } - - i--; - } - else { - STRING *substr = NULL; - string_substr(interpreter, pat, i, 1, &substr); - targ = string_concat(interpreter, targ, substr, 0); - } - } - - mem_sys_free(t1); - mem_sys_free(t2); + SPRINTF_OBJ obj = va_core; + obj.data = &args; - return targ; + return Parrot_sprintf_format(interpreter, pat, &obj); } - STRING * Parrot_vsprintf_c(struct Parrot_Interp *interpreter, const char *pat, - va_list *args) + va_list args) { STRING *realpat = string_make(interpreter, pat, strlen(pat), NULL, 0, NULL); @@ -499,18 +52,18 @@ Parrot_vsprintf_c(struct Parrot_Interp *interpreter, const char *pat, void Parrot_vsprintf(struct Parrot_Interp *interpreter, char *targ, const char *pat, - va_list *args) + va_list args) { STRING *ret = Parrot_vsprintf_c(interpreter, pat, args); -/* string_transcode(interpreter, ret, NULL, NULL, &ret);*/ + string_transcode(interpreter, ret, NULL, NULL, &ret); memcpy(targ, ret->strstart, ret->bufused); - targ[ret->bufused + 1] = 00; + targ[ret->bufused + 1] = '\0'; } void Parrot_vsnprintf(struct Parrot_Interp *interpreter, char *targ, - UINTVAL len, const char *pat, va_list *args) + size_t len, const char *pat, va_list args) { STRING *ret = Parrot_vsprintf_c(interpreter, pat, args); string_transcode(interpreter, ret, NULL, NULL, &ret); @@ -531,7 +84,7 @@ Parrot_sprintf_s(struct Parrot_Interp *interpreter, STRING *pat, ...) va_start(args, pat); - ret = Parrot_vsprintf_s(interpreter, pat, &args); + ret = Parrot_vsprintf_s(interpreter, pat, args); va_end(args); @@ -546,7 +99,7 @@ Parrot_sprintf_c(struct Parrot_Interp *interpreter, const char *pat, ...) va_start(args, pat); - ret = Parrot_vsprintf_c(interpreter, pat, &args); + ret = Parrot_vsprintf_c(interpreter, pat, args); va_end(args); @@ -561,24 +114,33 @@ Parrot_sprintf(struct Parrot_Interp *interpreter, char *targ, const char *pat, va_start(args, pat); - Parrot_vsprintf(interpreter, targ, pat, &args); + Parrot_vsprintf(interpreter, targ, pat, args); va_end(args); } void -Parrot_snprintf(struct Parrot_Interp *interpreter, char *targ, UINTVAL len, +Parrot_snprintf(struct Parrot_Interp *interpreter, char *targ, size_t len, const char *pat, ...) { va_list args; va_start(args, pat); - Parrot_vsnprintf(interpreter, targ, len, pat, &args); + Parrot_vsnprintf(interpreter, targ, len, pat, args); va_end(args); } +STRING * +Parrot_psprintf(struct Parrot_Interp *interpreter, STRING *pat, PMC * ary) +{ + SPRINTF_OBJ obj = pmc_core; + obj.data = ary; + + return Parrot_sprintf_format(interpreter, pat, &obj); +} + /* * Local variables: * c-indentation-style: bsd diff --git a/ops/core.ops b/ops/core.ops index 7b9d3a5fb0..28829f8441 100644 --- a/ops/core.ops +++ b/ops/core.ops @@ -2155,8 +2155,38 @@ inline op pack(inout STR, in INT, in INT, in INT) { goto NEXT(); } +=item C(out STR, in STR, in PMC) + +=item C(out PMC, in PMC, in PMC) + +=item C(out STR, in STR) [unimplemented] + +=item C(out PMC, in PMC) [unimplemented] + +Sets $1 to the result of calling C with the +given format ($2) and arguments ($3, which should be an ordered +aggregate PMC). In the (unimplemented) versions that don't include +$3, arguments are popped off the user stack. + +The result is quite similar to using the system C, but is +protected against buffer overflows and the like. There are some +differences, especially concerning sizes (which are largely ignored); +see F for details. + =back +inline op sprintf(out STR, in STR, in PMC) { + $1=Parrot_psprintf(interpreter, $2, $3); + goto NEXT(); +} + +inline op sprintf(out PMC, in PMC, in PMC) { + $1->vtable->set_string_native(interpreter, $1, + Parrot_psprintf(interpreter, $2->vtable->get_string(interpreter, $2), $3) + ); + goto NEXT(); +} + =cut ############################################################################### diff --git a/ops/debug.ops b/ops/debug.ops index af848197a2..5174c78cb1 100644 --- a/ops/debug.ops +++ b/ops/debug.ops @@ -119,8 +119,8 @@ Print all the parrot registers at once. op debug_print() { if (!(interpreter->pdb->state & PDB_BREAK)) { - PDB_print_int(&interpreter->ctx.int_reg, -1); - PDB_print_num(&interpreter->ctx.num_reg, -1); + PDB_print_int(interpreter, &interpreter->ctx.int_reg, -1); + PDB_print_num(interpreter, &interpreter->ctx.num_reg, -1); PDB_print_string(interpreter,&interpreter->ctx.string_reg, -1); PDB_print_pmc(interpreter,&interpreter->ctx.pmc_reg, -1, NULL); } diff --git a/packdump.c b/packdump.c index f930d61f04..83c3bb2051 100644 --- a/packdump.c +++ b/packdump.c @@ -18,28 +18,28 @@ PackFile_dump(struct PackFile *self) { size_t i; - printf("FIXUP => {\n"); + PIO_printf(NULL, "FIXUP => {\n"); PackFile_FixupTable_dump(self->fixup_table); - printf("},\n"); + PIO_printf(NULL, "},\n"); - printf("CONST => [\n"); + PIO_printf(NULL, "CONST => [\n"); PackFile_ConstTable_dump(self->const_table); - printf("],\n"); + PIO_printf(NULL, "],\n"); - printf("BCODE => [ # %ld bytes", (long)self->byte_code_size); + PIO_printf(NULL, "BCODE => [ # %ld bytes", (long)self->byte_code_size); for (i = 0; i < self->byte_code_size / sizeof(opcode_t); i++) { if (i % 8 == 0) { - printf("\n %08lx: ", (unsigned long)i * sizeof(opcode_t)); + PIO_printf(NULL, "\n %08lx: ", (unsigned long)i * sizeof(opcode_t)); } - printf("%08lx ", (unsigned long)self->byte_code[i]); + PIO_printf(NULL, "%08lx ", (unsigned long)self->byte_code[i]); } - printf("\n]\n"); + PIO_printf(NULL, "\n]\n"); return; } @@ -57,12 +57,12 @@ PackFile_ConstTable_dump(struct PackFile_ConstTable *self) opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_dump: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_dump: self == NULL!\n"); return; } for (i = 0; i < self->const_count; i++) { - printf(" # %ld:\n", (long)i); + PIO_printf(NULL, " # %ld:\n", (long)i); PackFile_Constant_dump(self->constants[i]); } @@ -80,23 +80,23 @@ PackFile_Constant_dump(struct PackFile_Constant *self) switch (self->type) { case PFC_NONE: /* TODO: OK to be silent here? */ - printf(" [ 'PFC_NONE', undef ],\n"); + PIO_printf(NULL," [ 'PFC_NONE', undef ],\n"); break; case PFC_NUMBER: - printf(" [ 'PFC_NUMBER', %g ],\n", self->number); + PIO_printf(NULL, " [ 'PFC_NUMBER', %g ],\n", self->number); break; case PFC_STRING: - printf(" [ 'PFC_STRING', {\n"); - printf(" FLAGS => 0x%04lx,\n", (long)self->string->flags); - printf(" ENCODING => %s,\n", self->string->encoding->name); - printf(" TYPE => %s,\n", self->string->type->name); - printf(" SIZE => %ld,\n", (long)self->string->bufused); + PIO_printf(NULL, " [ 'PFC_STRING', {\n"); + PIO_printf(NULL, " FLAGS => 0x%04lx,\n", (long)self->string->flags); + PIO_printf(NULL, " ENCODING => %s,\n", self->string->encoding->name); + PIO_printf(NULL, " TYPE => %s,\n", self->string->type->name); + PIO_printf(NULL, " SIZE => %ld,\n", (long)self->string->bufused); /* TODO: Won't do anything reasonable for most encodings */ - printf(" DATA => '%.*s'\n", + PIO_printf(NULL, " DATA => '%.*s'\n", (int)self->string->bufused, (char *)self->string->strstart); - printf(" } ],\n"); + PIO_printf(NULL, " } ],\n"); break; default: diff --git a/packfile.c b/packfile.c index 81687bea95..164149067d 100644 --- a/packfile.c +++ b/packfile.c @@ -48,14 +48,14 @@ PackFile_new(void) struct PackFile *pf = mem_sys_allocate(sizeof(struct PackFile)); if (!pf) { - fprintf(stderr, "PackFile_new: Unable to allocate!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate!\n"); return NULL; } pf->header = mem_sys_allocate(sizeof(struct PackFile_Header)); if(!pf->header) { - fprintf(stderr, "PackFile_new: Unable to allocate header!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate header!\n"); PackFile_destroy(pf); return NULL; } @@ -65,7 +65,7 @@ PackFile_new(void) mem_sys_allocate(sizeof(struct PackFile_FixupTable)); if (!pf->fixup_table) { - fprintf(stderr, "PackFile_new: Unable to allocate fixup table!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate fixup table!\n"); PackFile_destroy(pf); return NULL; } @@ -76,7 +76,7 @@ PackFile_new(void) mem_sys_allocate(sizeof(struct PackFile_ConstTable)); if (!pf->const_table) { - fprintf(stderr, "PackFile_new: Unable to allocate constant table!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate constant table!\n"); PackFile_destroy(pf); return NULL; } @@ -106,7 +106,7 @@ PackFile_fetch_op(struct PackFile *pf, opcode_t *stream) { if(pf->fetch_op == NULL) return *stream; #if TRACE_PACKFILE == 2 - fprintf(stderr, "PackFile_fetch_op: Reordering.\n"); + PIO_eprintf(NULL, "PackFile_fetch_op: Reordering.\n"); #endif return (pf->fetch_op)(*stream); } @@ -148,14 +148,14 @@ PackFile_fetch_nv(struct PackFile *pf, opcode_t *stream) { FLOATVAL f; if(pf->fetch_nv == NULL) { #if TRACE_PACKFILE - fprintf(stderr, "PackFile_fetch_nv: Native [%d bytes]..\n", + PIO_eprintf(NULL, "PackFile_fetch_nv: Native [%d bytes]..\n", sizeof(FLOATVAL)); #endif memcpy(&f, stream, sizeof(FLOATVAL)); return f; } #if TRACE_PACKFILE - fprintf(stderr, "PackFile_fetch_nv: Byteordering..\n"); + PIO_eprintf(NULL, "PackFile_fetch_nv: Byteordering..\n"); #endif /* Here is where the size transforms get messy */ (pf->fetch_nv)((unsigned char *)&f, (unsigned char *)stream); @@ -184,7 +184,7 @@ void PackFile_assign_transforms(struct PackFile *pf) { } # if TRACE_PACKFILE else { - fprintf(stderr, "header->byteorder [%d] native byteorder [%d]\n", + PIO_eprintf(NULL, "header->byteorder [%d] native byteorder [%d]\n", pf->header->byteorder, PARROT_BIGENDIAN); } # endif @@ -205,7 +205,7 @@ void PackFile_destroy(struct PackFile *pf) { if (!pf) { - fprintf(stderr, "PackFile_destroy: pf == NULL!\n"); + PIO_eprintf(NULL, "PackFile_destroy: pf == NULL!\n"); return; } @@ -235,12 +235,12 @@ static INTVAL PackFile_check_segment_size(opcode_t segment_size, const char *debug) { #if TRACE_PACKFILE - printf("PackFile_unpack(): Unpacking %ld bytes for %s table...\n", + PIO_eprintf(NULL, "PackFile_unpack(): Unpacking %ld bytes for %s table...\n", segment_size, debug); #endif if (segment_size % sizeof(opcode_t)) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Illegal %s table segment size %ld (must be multiple of %ld)!\n", debug, segment_size, (long)sizeof(opcode_t)); return 0; @@ -291,7 +291,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, int i; if (!self) { - fprintf(stderr, "PackFile_unpack: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_unpack: self == NULL!\n"); return 0; } @@ -304,7 +304,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, if(header->wordsize != sizeof(opcode_t)) { self->need_wordsize = 1; if(header->wordsize == 0) { - fprintf(stderr, "PackFile_unpack: Invalid wordsize %d\n", + PIO_eprintf(NULL, "PackFile_unpack: Invalid wordsize %d\n", header->wordsize); return 0; } @@ -313,17 +313,17 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, PackFile_assign_transforms(self); #if TRACE_PACKFILE - fprintf(stderr, "wordsize: %d\n", header->wordsize); - fprintf(stderr, "byteorder: %d\n", header->byteorder); + PIO_eprintf(NULL, "wordsize: %d\n", header->wordsize); + PIO_eprintf(NULL, "byteorder: %d\n", header->byteorder); #endif /* * FIXME */ if(self->need_wordsize) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Unimplemented wordsize transform.\n"); - fprintf(stderr, "File has wordsize: %d (native is %d)\n", + PIO_eprintf(NULL, "File has wordsize: %d (native is %d)\n", header->wordsize, sizeof(opcode_t)); return 0; } @@ -337,9 +337,9 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, * The magic and opcodetype fields are in native byteorder. */ if (header->magic != PARROT_MAGIC) { - fprintf(stderr, "PackFile_unpack: Not a Parrot PackFile!\n"); + PIO_eprintf(NULL, "PackFile_unpack: Not a Parrot PackFile!\n"); #if TRACE_PACKFILE - fprintf(stderr, "Magic number was [%x] not [%x]\n", + PIO_eprintf(NULL, "Magic number was [%x] not [%x]\n", header->magic, PARROT_MAGIC); #endif return 0; @@ -348,7 +348,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, header->opcodetype = PackFile_fetch_op(self, cursor++); #if TRACE_PACKFILE - fprintf(stderr, "PackFile_unpack(): Magic verified.\n"); + PIO_eprintf(NULL, "PackFile_unpack(): Magic verified.\n"); #endif /* @@ -363,7 +363,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, if (!PackFile_FixupTable_unpack(self->fixup_table, cursor, header->fixup_ss)) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Error reading fixup table segment!\n"); return 0; } @@ -383,7 +383,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, if (!PackFile_ConstTable_unpack(interpreter, self, self->const_table, cursor, header->const_ss)) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Error reading constant table segment!\n"); return 0; } @@ -407,7 +407,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, self->byte_code = mem_sys_allocate(self->byte_code_size); if (!self->byte_code) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Unable to allocate memory to copy byte code!\n"); self->byte_code_size = 0; return 0; @@ -422,7 +422,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, for(i = 0; i < (int)(self->byte_code_size / sizeof(opcode_t)); i++) { self->byte_code[i] = PackFile_fetch_op(self, cursor++); #if TRACE_PACKFILE - fprintf(stderr, "op[%u]->[%u]\n", *(cursor-1), + PIO_eprintf(NULL, "op[%u]->[%u]\n", *(cursor-1), self->byte_code[i]); #endif } @@ -453,7 +453,7 @@ void PackFile_FixupTable_clear(struct PackFile_FixupTable *self) { if (!self) { - fprintf(stderr, "PackFile_FixupTable_clear: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_FixupTable_clear: self == NULL!\n"); return; } @@ -507,7 +507,7 @@ PackFile_ConstTable_clear(struct PackFile_ConstTable *self) opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_clear: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_clear: self == NULL!\n"); return; } @@ -551,7 +551,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_unpack: self == NULL!\n"); + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack: self == NULL!\n"); return 0; } @@ -562,7 +562,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, self->const_count = PackFile_fetch_op(pf, cursor++); #if TRACE_PACKFILE - printf("PackFile_ConstTable_unpack(): Unpacking %ld constants...\n", + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack(): Unpacking %ld constants...\n", self->const_count); #endif @@ -575,7 +575,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, sizeof(struct PackFile_Constant *)); if (!self->constants) { - fprintf(stderr, + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack: Could not allocate memory for array!\n"); self->const_count = 0; return 0; @@ -584,7 +584,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, for (i = 0; i < self->const_count; i++) { INTVAL rc; #if TRACE_PACKFILE - printf("PackFile_ConstTable_unpack(): Unpacking constant %ld...\n", i); + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack(): Unpacking constant %ld...\n", i); #endif self->constants[i] = PackFile_Constant_new(); @@ -644,7 +644,7 @@ void PackFile_Constant_destroy(struct PackFile_Constant *self) { if (!self) { - fprintf(stderr, "PackFile_Constant_destroy: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_Constant_destroy: self == NULL!\n"); return; } @@ -668,7 +668,7 @@ PackFile_Constant_destroy(struct PackFile_Constant *self) break; default: - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_Constant_clear: Unrecognized type '%c' (%ld)!\n", (char)self->type, self->type); return; @@ -784,9 +784,9 @@ PackFile_Constant_unpack(struct Parrot_Interp *interpreter, size = PackFile_fetch_op(pf, cursor++); #if TRACE_PACKFILE - printf("PackFile_Constant_unpack(): Type is %ld ('%c')...\n", type, + PIO_eprintf(NULL, "PackFile_Constant_unpack(): Type is %ld ('%c')...\n", type, (char)type); - printf("PackFile_Constant_unpack(): Size is %ld...\n", size); + PIO_eprintf(NULL, "PackFile_Constant_unpack(): Size is %ld...\n", size); #endif switch (type) { @@ -807,7 +807,7 @@ PackFile_Constant_unpack(struct Parrot_Interp *interpreter, break; default: - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_Constant_clear: Unrecognized type '%c' during unpack!\n", (char)type); return 0; @@ -860,7 +860,7 @@ PackFile_Constant_unpack_number(struct PackFile * pf, * determined by Configure. */ #if TRACE_PACKFILE - fprintf(stderr, + PIO_eprintf(NULL, "FIXME: PackFile_Constant_unpack_number: assuming size of FLOATVAL!\n"); #endif self->number = PackFile_fetch_nv(pf, (opcode_t *)cursor); @@ -921,11 +921,11 @@ PackFile_Constant_unpack_string(struct Parrot_Interp *interpreter, size = (size_t)PackFile_fetch_op(pf, cursor++); #if TRACE_PACKFILE - printf("PackFile_Constant_unpack_string(): flags are 0x%04x...\n", flags); - printf("PackFile_Constant_unpack_string(): encoding is %ld...\n", + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): flags are 0x%04x...\n", flags); + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): encoding is %ld...\n", encoding); - printf("PackFile_Constant_unpack_string(): type is %ld...\n", type); - printf("PackFile_Constant_unpack_string(): size is %ld...\n", size); + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): type is %ld...\n", type); + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): size is %ld...\n", size); #endif self->type = PFC_STRING; diff --git a/packout.c b/packout.c index 8c819efb2b..96fadba467 100644 --- a/packout.c +++ b/packout.c @@ -37,23 +37,23 @@ PackFile_pack_size(struct PackFile *self) segment_length_size = sizeof(opcode_t); #if TRACE_PACKFILE - printf("getting fixup table size...\n"); + PIO_eprintf(NULL, "getting fixup table size...\n"); #endif fixup_table_size = PackFile_FixupTable_pack_size(self->fixup_table); #if TRACE_PACKFILE - printf(" ... it is %ld\n", fixup_table_size); + PIO_eprintf(NULL, " ... it is %ld\n", fixup_table_size); #endif #if TRACE_PACKFILE - printf("getting const table size...\n"); + PIO_eprintf(NULL, "getting const table size...\n"); #endif const_table_size = PackFile_ConstTable_pack_size(self->const_table); #if TRACE_PACKFILE - printf(" ... it is %ld\n", const_table_size); + PIO_eprintf(NULL, " ... it is %ld\n", const_table_size); #endif return header_size + magic_size + oct_size @@ -161,7 +161,7 @@ PackFile_ConstTable_pack_size(struct PackFile_ConstTable *self) opcode_t size = 0; if (!self) { - fprintf(stderr, "PackFile_ConstTable_size: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_size: self == NULL!\n"); return -1; } @@ -188,7 +188,7 @@ PackFile_ConstTable_pack(struct PackFile *packfile, opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_pack: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_pack: self == NULL!\n"); return; } @@ -222,7 +222,7 @@ static int find_in_const(PMC *key, int type) else if (type == PFC_NUMBER && ct->constants[i]->number == key->cache.num_val) return i; - fprintf(stderr, "find_in_const: couldn't find const for key\n"); + PIO_eprintf(NULL, "find_in_const: couldn't find const for key\n"); exit(1); } /*************************************** @@ -360,7 +360,7 @@ PackFile_Constant_pack(struct PackFile_Constant *self, opcode_t *packed) *cursor++ = key->cache.int_val; break; default: - fprintf(stderr, "PackFile_Constant_pack: " + PIO_eprintf(NULL, "PackFile_Constant_pack: " "unsupported constant type\n"); exit(1); } @@ -371,7 +371,7 @@ PackFile_Constant_pack(struct PackFile_Constant *self, opcode_t *packed) default: /* TODO: OK to be silent here? */ /* ARGH, don't be silent -lt */ - fprintf(stderr, "PackFile_Constant_pack: unsupported constant\n"); + PIO_eprintf(NULL, "PackFile_Constant_pack: unsupported constant\n"); exit(1); break; } diff --git a/runops_cores.c b/runops_cores.c index b8e48c5eda..5f52f354f7 100644 --- a/runops_cores.c +++ b/runops_cores.c @@ -52,7 +52,7 @@ runops_cgoto_core(struct Parrot_Interp *interpreter, opcode_t *pc) pc = cg_core(pc, interpreter); return pc; #else - fprintf(stderr, "Computed goto unavailable in this configuration.\n"); + PIO_eprintf(interpreter, "Computed goto unavailable in this configuration.\n"); exit(1); #endif } diff --git a/spf_render.c b/spf_render.c new file mode 100644 index 0000000000..b47f871764 --- /dev/null +++ b/spf_render.c @@ -0,0 +1,646 @@ +/* spf_render.c + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id$ + * Overview: + * Implements the main function that drives the Parrot_sprintf + * family and its utility functions. + * Data Structure and Algorithms: + * History: + * Notes: + * References: misc.h, misc.c, spf_vtable.c + */ + +#define IN_SPF_SYSTEM + +#include "parrot/parrot.h" + +/* Per Dan's orders, we will not use sprintf if snprintf isn't + * around for us. + */ +#ifdef _WIN32 +# define snprintf _snprintf +#endif + +/* UTILITY FUNCTIONS */ + +static void +uint_to_str(struct Parrot_Interp *interpreter, STRING *out, + char *tc, UHUGEINTVAL num, char base) +{ + int i = 0, cur2; + char cur; + + do { + cur = (char)(num % base); + + if (cur < 10) { + tc[i] = (char)('0' + cur); + } + else { + tc[i] = (char)('a' + cur - 10); + } + + i++; + } while (num /= base); + + cur2 = i - 1; + + /* This fixes the problems some people have experienced + * with precision--the string was being reused without + * being cleared first. + */ + if(string_compare(interpreter, out, cstr2pstr("-")) != 0) { + string_set(interpreter, out, cstr2pstr("")); + } + + for (i = 0; i <= cur2; i++) { + string_append(interpreter, out, char2pstr(tc[cur2 - i]), 0); + } +} + +static void +int_to_str(struct Parrot_Interp *interpreter, STRING *out, + char *tc, HUGEINTVAL num, char base) +{ + string_set(interpreter, out, cstr2pstr("")); + + if (num < 0) { + string_append(interpreter, out, cstr2pstr("-"), 0); + num = -num; + } + uint_to_str(interpreter, out, tc, (UHUGEINTVAL) num, base); +} + +/* handle +, -, 0, #, space, width, and prec. */ +static void +handle_flags(struct Parrot_Interp *interpreter, + SpfInfo info, STRING *str, INTVAL is_int_type, const char *prefix) +{ + UINTVAL i; + UINTVAL len = string_length(str); + + if (is_int_type) { + /* +, space */ + if (string_ord(str, 0) != '-') { + if (info->flags & FLAG_PLUS) { + string_set(interpreter, str, + string_concat(interpreter, cstr2pstr("+"), str, 0)); + len++; + } + else if (info->flags & FLAG_SPACE) { + string_set(interpreter, str, + string_concat(interpreter, cstr2pstr(" "), str, 0)); + len++; + } + } + + /* # */ + if (info->flags & FLAG_SHARP && prefix && prefix[0]) { + string_set(interpreter, str, + string_concat(interpreter, cstr2pstr(prefix), str, 0)); + len += strlen(prefix); + } + + /* precision */ + if (info->flags & FLAG_PREC) { + info->flags |= FLAG_WIDTH; + if (string_ord(str, 0) == '-' || string_ord(str, 0) == '+') { + info->width = info->prec + 1; + } + else { + info->width = info->prec; + } + } + } + else { + /* string precision */ + if (info->flags & FLAG_PREC && info->prec < len) { + string_chopn(str, -(info->prec)); + len = info->prec; + } + } + + if (info->flags & FLAG_WIDTH) { + STRING *fill; + + if (info->flags & FLAG_ZERO) { + fill = cstr2pstr("0"); + } + else { + fill = cstr2pstr(" "); + } + + string_repeat(interpreter, fill, info->width - (len - 1), &fill); + + if (info->flags & FLAG_MINUS) { /* left-align */ + string_append(interpreter, str, fill, 0); + } + else { /* right-align */ + string_set(interpreter, str, string_concat(interpreter, + fill, str, 0)); + } + } +} + + +/* Turn the info structure back into an sprintf format. Far from being + * pointless, this is used to call snprintf() when we're confronted with + * a float. + */ + +static void +gen_sprintf_call(struct Parrot_Interp *interpreter, STRING *ts, char *out, + SpfInfo info, char thingy) +{ + int i = 0; + char tc[PARROT_SPRINTF_BUFFER_SIZE]; + out[i++] = '%'; + + if (info->flags) { + if (info->flags & FLAG_MINUS) { + out[i++] = '-'; + } + if (info->flags & FLAG_PLUS) { + out[i++] = '+'; + } + if (info->flags & FLAG_ZERO) { + out[i++] = '0'; + } + if (info->flags & FLAG_SPACE) { + out[i++] = ' '; + } + if (info->flags & FLAG_SHARP) { + out[i++] = '#'; + } + } + + if (info->flags & FLAG_WIDTH) { + if (info->width > PARROT_SPRINTF_BUFFER_SIZE - 1) { + info->width = PARROT_SPRINTF_BUFFER_SIZE; + } + uint_to_str(interpreter, ts, tc, info->width, 10); + strcpy(out + i, string_to_cstring(interpreter, ts)); + i = strlen(out); + } + + if (info->flags & FLAG_PREC) { + if (info->prec > PARROT_SPRINTF_MAX_PREC) { + info->prec = PARROT_SPRINTF_MAX_PREC; + } + + out[i++] = '.'; + uint_to_str(interpreter, ts, tc, info->prec, 10); + strcpy(out + i, string_to_cstring(interpreter, ts)); + i = strlen(out); + } + + out[i++] = thingy; + out[i] = 0; +} + + +/* This is the engine that does all the formatting. */ + +STRING * +Parrot_sprintf_format(struct Parrot_Interp *interpreter, STRING *pat, + SPRINTF_OBJ * obj) +{ + INTVAL i; + STRING *targ = string_make(interpreter, NULL, 0, NULL, 0, NULL); + + /* ts is used almost universally as an intermediate target; + * tc is used as a temporary buffer by uint_to_string and + * as a target by gen_sprintf_call. + */ + STRING *ts; + char tc[PARROT_SPRINTF_BUFFER_SIZE]; + + + for (i = 0; i < (INTVAL) string_length(pat); i++) { + if (string_ord(pat, i) == '%') { /* % */ + if (string_ord(pat, i + 1) == '%') { + i++; + } + else { + /* hoo boy, here we go... */ + + /* Various data types we may need */ + void *ptr; + STRING *string; + PMC *pmc; + HUGEFLOATVAL thefloat; + HUGEINTVAL theint = 0; + UHUGEINTVAL theuint = 0; + + /* Storage for flags, etc. */ + struct spfinfo_t info = { 0, 0, 0, 0, 0 }; + + /* Reset temporaries */ + ts = string_make(interpreter, NULL, 0, NULL, 0, NULL); + tc[0] = '\0'; + +/* This can be really hard to understand, so I'll try to explain beforehand. + * A rough grammar for a printf format is: + * + * grammar Parrot::PrintF_Format { + * rule format { + * ( )* + * } + * + * rule other_stuff { + * <[^\%]> | \%\% + * } + * + * rule field { + * \% + * ? + * ? + * [\.]? + * ? + * + * } + * + * rule flags { + * <[ + * + # prefix with a + if necessary + * - # left-align + * 0 # zero-pad + * # space-pad + * \# # 0, 0x on octal, hex; force decimal point on float + * ]>+ + * } + * + * rule width { + * [\d|\*]+ # minimum width + * } + * + * rule prec { + * [\d|\*]+ # width on integers; + * # number of digits after decimal on floats; + * # maximum width on strings + * } + * + * rule size { + * <[ + * h # short (or float) + * l # long + * H # HUGEwhateverVAL (long [long]?, [long]? double) + * v # whateverVAL + * O # opcode_t + * P # really a PMC + * S # Parrot string (only with %s) + * ]> + * } + * + * rule term { + * <[ + * c # char + * d # integer + * i # integer + * o # octal + * x # hex + * X # hex with capital X (if #) + * b # binary + * B # binary with capital B (if #) + * u # unsigned integer + * p # pointer + * + * e # 1e1 + * E # 1E1 + * f # 1.0 + * g # 1, 0.1, 1e1 + * G # 1, 0.1, 1E1 + * + * s # string + * ]> + * } + * } + * + * Complication: once upon a time, %P existed. Now you should + * use %Ps, %Pd or %Pf, but we still need to support the old form. + * The same is true of %S--%Ss is the best form, but %S is still + * supported. + * + * The implementation of Parrot_vsprintf is surprisingly similar to this + * regex, even though the two were developed semi-independently. + * Parrot_vsprintf keeps track of what it expects to see next (the + * 'phase')--flags, width, precision, size, or field type (term). If it + * doesn't find a character that fits whatever it's expecting, it sets + * info.phase to the next thing and tries it. The first four phases just + * set flags--the last does all the work. + */ + + for (i++; i < (INTVAL) string_length(pat) + && info.phase != PHASE_DONE; i++) { + INTVAL ch = string_ord(pat, i); + + switch (info.phase) { + /*@fallthrough@ */ case PHASE_FLAGS: + switch (ch) { + case '-': + info.flags |= FLAG_MINUS; + break; + + case '+': + info.flags |= FLAG_PLUS; + break; + + case '0': + info.flags |= FLAG_ZERO; + break; + + case ' ': + info.flags |= FLAG_SPACE; + break; + + case '#': + info.flags |= FLAG_SHARP; + break; + + default: + info.phase = PHASE_WIDTH; + } + + + /*@fallthrough@ */ case PHASE_WIDTH: + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '8': + case '9': + info.flags |= FLAG_WIDTH; + info.width *= 10; + info.width += ch - '0'; + continue; + + case '*': + info.flags |= FLAG_WIDTH; + info.width *= 10; + info.width += obj->getint(interpreter, + SIZE_XVAL, obj); + continue; + + case '.': + info.phase = PHASE_PREC; + continue; + + default: + info.phase = PHASE_PREC; + } + + + /*@fallthrough@ */ case PHASE_PREC: + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '8': + case '9': + info.flags |= FLAG_PREC; + info.prec *= 10; + info.prec += ch - '0'; + continue; + + case '*': + info.flags |= FLAG_PREC; + info.prec *= 10; + info.prec += obj->getint(interpreter, + SIZE_XVAL, obj); + continue; + + default: + info.phase = PHASE_TYPE; + } + + /*@fallthrough@ */ case PHASE_TYPE: + switch (ch) { + case 'h': + info.type = SIZE_SHORT; + continue; + + case 'l': + info.type = SIZE_LONG; + continue; + + case 'H': + info.type = SIZE_HUGE; + continue; + + case 'v': + info.type = SIZE_XVAL; + continue; + + case 'O': + info.type = SIZE_OPCODE; + continue; + + case 'P': + info.type = SIZE_PMC; + continue; + + case 'S': + info.type = SIZE_PSTR; + continue; + + default: + info.phase = PHASE_TERM; + } + + + /*@fallthrough@ */ case PHASE_TERM: + switch (ch) { + /* INTEGERS */ + case 'c': + string_append(interpreter, targ, + obj->getchr(interpreter, + info.type, obj), 0); + break; + + case 'd': + case 'i': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 10); + + handle_flags(interpreter, &info, ts, 1, NULL); + + string_append(interpreter, targ, ts, 0); + break; + + case 'o': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 8); + + handle_flags(interpreter, &info, ts, 1, "0"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'x': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 16); + + handle_flags(interpreter, &info, ts, 1, "0x"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'X': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 16); + + handle_flags(interpreter, &info, ts, 1, "0X"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'b': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 2); + + handle_flags(interpreter, &info, ts, 1, "0b"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'B': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 2); + + handle_flags(interpreter, &info, ts, 1, "0B"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'u': + theuint = + obj->getuint(interpreter, info.type, obj); + uint_to_str(interpreter, ts, tc, theuint, 10); + + handle_flags(interpreter, &info, ts, 1, NULL); + + string_append(interpreter, targ, ts, 0); + break; + + case 'p': + ptr = obj->getptr(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, + (HUGEINTVAL) (size_t) ptr, 16); + + handle_flags(interpreter, &info, ts, 1, "0x"); + + string_append(interpreter, targ, ts, 0); + break; + + /* FLOATS - We cheat on these and use snprintf. */ + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + thefloat = obj->getfloat + (interpreter, info.type, obj); + gen_sprintf_call(interpreter, ts, tc, &info, ch); + string_set(interpreter, ts, cstr2pstr(tc)); + /* XXX lost precision if %Hg or whatever */ + snprintf(tc, PARROT_SPRINTF_BUFFER_SIZE, + string_to_cstring(interpreter, ts), + (double)thefloat); + +#if _WIN32 + /* Microsoft uses a retarded, broken, nonstandard + * behavior with regards to signs, exponents and + * precision: it doesn't count the + as part of the + * precision. We'll fix it ourselves if need be. + * XXX this bug might also apply to %e and %E + */ + + if(tolower(ch) == 'g') { + UINTVAL i; + for(i=0; i < strlen(tc); i++) { + if(tolower(tc[i]) == 'e' && + (tc[i+1] == '+' || tc[i+1] == '-')) { + tc[i+2]='\0'; + strcat(tc, &(tc[i+3])); + } + } + } +#endif + + string_append(interpreter, targ, cstr2pstr(tc), 0); + break; + + /* STRINGS */ + case 's': + CASE_s: + string = obj->getstring + (interpreter, info.type, obj); + + string_set(interpreter, ts, string); + + handle_flags(interpreter, &info, ts, 0, NULL); + + string_append(interpreter, targ, ts, 0); + + break; + + default: + /* fake the old %P and %S commands */ + if (info.type == SIZE_PMC + || info.type == SIZE_PSTR) { + i--; + goto CASE_s; + /* case 's' will see the SIZE_PMC or SIZE_PSTR + * and assume it was %Ps (or %Ss). Genius, + * no? + */ + } + else { + internal_exception(INVALID_CHARACTER, + "'%c' is not a valid sprintf format", + ch); + } + } + + info.phase = PHASE_DONE; + break; + + case PHASE_DONE: + /* This is the terminating condition of the surrounding + * loop, so... + */ + PANIC("We can't be here"); + } + } + } + + i--; + } + else { + STRING *substr = NULL; + string_substr(interpreter, pat, i, 1, &substr); + string_append(interpreter, targ, substr, 0); + } + } + + return targ; +} + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: +*/ diff --git a/spf_vtable.c b/spf_vtable.c new file mode 100644 index 0000000000..17da23a1dd --- /dev/null +++ b/spf_vtable.c @@ -0,0 +1,305 @@ +/* spf_vtable.c + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id$ + * Overview: + * Implements the two families of functions Parrot_sprintf + * may use to retrieve arguments. + * Data Structure and Algorithms: + * History: + * When I was first working on this implementation of + * sprintf, I ran into a problem. I wanted to re-use the + * implementation for a Parrot bytecode-level sprintf, but + * that couldn't be done, since it used va_* directly. For + * a while I thought about generating two versions of the + * source with a Perl script, but that seemed like overkill. + * Eventually I came across this idea--pass in a specialized + * vtable with methods for extracting things from the arglist, + * whatever it happened to be. This is the result. + * Notes: + * In the future, it may be deemed desirable to similarly + * vtable-ize appending things to the string, allowing for + * faster PIO_printf &c, as well as a version that writes + * directly to a C string. However, at this point neither + * of those is needed. + * References: misc.h, misc.c, spf_render.c + */ + +#define IN_SPF_SYSTEM + +#include "parrot/parrot.h" + +#include + +/* VARARGS CORE */ + +static STRING * +getchr_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + char ch = va_arg(*arg, char); + return string_make(interpreter, &ch, 1, NULL, 0, NULL); +} + +static HUGEINTVAL +getint_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_REG: + return (HUGEINTVAL) (int)va_arg(*arg, int); + case SIZE_SHORT: + /* "'short int' is promoted to 'int' when passed through '...'" */ + return (HUGEINTVAL) (short)va_arg(*arg, int); + case SIZE_LONG: + return (HUGEINTVAL) (long)va_arg(*arg, long); + case SIZE_HUGE: + return (HUGEINTVAL) (HUGEINTVAL) + va_arg(*arg, HUGEINTVAL); + case SIZE_XVAL: + return (HUGEINTVAL) (INTVAL) va_arg(*arg, INTVAL); + case SIZE_OPCODE: + return (HUGEINTVAL) (opcode_t) va_arg(*arg, opcode_t); + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return (HUGEINTVAL) (INTVAL) + (pmc->vtable->get_integer(interpreter, pmc)); + } + default: + PANIC("Invalid int type!"); + return 0; + } +} + +static UHUGEINTVAL +getuint_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_REG: + return (UHUGEINTVAL) (unsigned int) + va_arg(*arg, unsigned int); + case SIZE_SHORT: + /* short int promoted HLAGHLAGHLAGH. See note above */ + return (UHUGEINTVAL) (unsigned short) + va_arg(*arg, unsigned int); + case SIZE_LONG: + return (UHUGEINTVAL) (unsigned long) + va_arg(*arg, unsigned long); + case SIZE_HUGE: + return (UHUGEINTVAL) (UHUGEINTVAL) + va_arg(*arg, UHUGEINTVAL); + case SIZE_XVAL: + return (UHUGEINTVAL) (UINTVAL) va_arg(*arg, UINTVAL); + case SIZE_OPCODE: + return (UHUGEINTVAL) (opcode_t) va_arg(*arg, opcode_t); + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return (UHUGEINTVAL) (UINTVAL) + (pmc->vtable->get_integer(interpreter, pmc)); + } + default: + PANIC("Invalid uint type!"); + return 0; + } +} + +static HUGEFLOATVAL +getfloat_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_SHORT: + return (HUGEFLOATVAL) (float)va_arg(*arg, float); + case SIZE_REG: + return (HUGEFLOATVAL) (double)va_arg(*arg, double); + case SIZE_HUGE: + return (HUGEFLOATVAL) (HUGEFLOATVAL) + va_arg(*arg, HUGEFLOATVAL); + case SIZE_XVAL: + return (HUGEFLOATVAL) (FLOATVAL) + va_arg(*arg, FLOATVAL); + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return (HUGEFLOATVAL) (pmc->vtable->get_number(interpreter, pmc)); + } + default: + internal_exception(INVALID_CHARACTER, + "Internal sprintf doesn't recognize size %d for a float", + size); + return (HUGEFLOATVAL) 0.0; + } +} + +static STRING * +getstring_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_REG:{ + char *cstr = (char *)va_arg(*arg, char *); + return cstr2pstr(cstr); + } + + case SIZE_PSTR: + return string_copy(interpreter, (STRING *) + va_arg(*arg, STRING *)); + + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return pmc->vtable->get_string(interpreter, pmc); + } + + default: + internal_exception(INVALID_CHARACTER, + "Internal sprintf doesn't recognize size %d for a string", + size); + return NULL; + } +} + +static void * +getptr_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + return (void *)va_arg(*arg, void *); +} + +SPRINTF_OBJ va_core = { + NULL, 0, getchr_va, getint_va, getuint_va, + getfloat_va, getstring_va, getptr_va +}; + + +/* PMC CORE */ + +static STRING * +getchr_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + return string_substr(interpreter, + tmp->vtable->get_string(interpreter, tmp), 0, 1, + NULL); +} + +static HUGEINTVAL +getint_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + HUGEINTVAL ret; + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + ret = (HUGEINTVAL) (tmp->vtable->get_integer(interpreter, tmp)); + + switch (size) { + case SIZE_SHORT: + ret = (HUGEINTVAL) (short)ret; + break; + /*case SIZE_REG: + * ret=(HUGEINTVAL)(int)ret; */ + break; + case SIZE_LONG: + ret = (HUGEINTVAL) (long)ret; + default: + /* nothing */ ; + } + + return ret; +} + +static UHUGEINTVAL +getuint_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + UHUGEINTVAL ret; + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + ret = (UHUGEINTVAL) (tmp->vtable->get_integer(interpreter, tmp)); + + switch (size) { + case SIZE_SHORT: + ret = (UHUGEINTVAL) (unsigned short)ret; + break; + /* case SIZE_REG: + * ret=(UHUGEINTVAL)(unsigned int)ret; + * break; */ + case SIZE_LONG: + ret = (UHUGEINTVAL) (unsigned long)ret; + default: + /* nothing */ ; + } + + return ret; +} + +static HUGEFLOATVAL +getfloat_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + HUGEFLOATVAL ret; + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + ret = (HUGEFLOATVAL) (tmp->vtable->get_number(interpreter, tmp)); + + switch (size) { + case SIZE_SHORT: + ret = (HUGEFLOATVAL) (float)ret; + break; + /* case SIZE_REG: + * ret=(HUGEFLOATVAL)(double)ret; + * break; */ + default: + /* nothing */ ; + } + + return ret; +} + +static STRING * +getstring_pmc(struct Parrot_Interp *interpreter, + INTVAL size, SPRINTF_OBJ * obj) +{ + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + return (STRING *)(tmp->vtable->get_string(interpreter, tmp)); +} + +static void * +getptr_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + /* XXX correct? */ + return (void *)(tmp->vtable->get_integer(interpreter, tmp)); +} + +SPRINTF_OBJ pmc_core = { + NULL, 0, getchr_pmc, getint_pmc, getuint_pmc, + getfloat_pmc, getstring_pmc, getptr_pmc +}; + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: +*/ diff --git a/src/debug.c b/src/debug.c index 403c051a05..48acde985f 100644 --- a/src/debug.c +++ b/src/debug.c @@ -215,18 +215,18 @@ PDB_get_command(struct Parrot_Interp *interpreter) while (pdb->cur_opcode != line->opcode) line = line->next; - fprintf(stderr,"\n%li ",line->number); + PIO_eprintf(interpreter, "\n%li ", line->number); c = pdb->file->source + line->source_offset; while (*c != '\n' && c) - fprintf(stderr,"%c",*(c++)); - fprintf(stderr,"\n"); + PIO_eprintf(interpreter, "%c", *(c++)); + PIO_eprintf(interpreter, "\n"); } i = 0; c = (char *)mem_sys_allocate(255); - fprintf(stderr,"\n(pdb) "); + PIO_eprintf(interpreter, "\n(pdb) "); /* skip leading whitespace */ do { @@ -331,7 +331,7 @@ PDB_run_command(struct Parrot_Interp *interpreter, const char *command) PDB_run_command(interpreter,pdb->last_command); break; default: - fprintf(stderr,"Undefined command: \"%s\". Try \"help\".", + PIO_eprintf(interpreter, "Undefined command: \"%s\". Try \"help\".", command); break; } @@ -448,7 +448,7 @@ PDB_cond(struct Parrot_Interp *interpreter, const char *command) condition->type = PDB_cond_pmc; break; default: - fprintf(stderr, "First argument must be a register\n"); + PIO_eprintf(interpreter, "First argument must be a register\n"); return NULL; } @@ -496,7 +496,7 @@ PDB_cond(struct Parrot_Interp *interpreter, const char *command) goto INV_COND; break; default: -INV_COND: fprintf(stderr, "Invalid condition\n"); +INV_COND: PIO_eprintf(interpreter, "Invalid condition\n"); return NULL; } @@ -580,7 +580,7 @@ PDB_set_break(struct Parrot_Interp *interpreter, const char *command) /* Abort if the line number provided doesn't exists */ if (!line->next) { - fprintf(stderr,"Can't set a breakpoint at line number %li\n",ln); + PIO_eprintf(interpreter, "Can't set a breakpoint at line number %li\n",ln); return; } } @@ -605,13 +605,13 @@ PDB_set_break(struct Parrot_Interp *interpreter, const char *command) /* Revive the breakpoint if was deleted */ if (sbreak && sbreak->skip == -1) { - fprintf(stderr,"Breakpoint %li at line %li\n",i,line->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Breakpoint %li at line %li\n",i,line->number); sbreak->skip = 0; return; } /* Don't do anything if there is already a breakpoint at this line */ if (sbreak) { - fprintf(stderr,"Breakpoint %li already at line %li\n",i,line->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Breakpoint %li already at line %li\n",i,line->number); return; } @@ -648,7 +648,7 @@ PDB_set_break(struct Parrot_Interp *interpreter, const char *command) pdb->breakpoint = newbreak; } - fprintf(stderr,"Breakpoint %li at line %li\n",i,line->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Breakpoint %li at line %li\n",i,line->number); } /* PDB_init @@ -694,7 +694,7 @@ PDB_init(struct Parrot_Interp *interpreter, const char *command) /* Restart if we are already running */ if (pdb->state & PDB_RUNNING) - fprintf(stderr,"Restating\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Restating\n"); /* Get the bytecode start */ pdb->cur_opcode = interpreter->code->byte_code; @@ -715,7 +715,7 @@ PDB_continue(struct Parrot_Interp *interpreter, /* Skip any breakpoint? */ if (command && *command) { if (!pdb->breakpoint) { - fprintf(stderr,"No breakpoints to skip\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"No breakpoints to skip\n"); return; } ln = atol(command); @@ -769,7 +769,7 @@ PDB_program_end(struct Parrot_Interp *interpreter) /* Remove the RUNNING state */ pdb->state &= ~PDB_RUNNING; - fprintf(stderr,"Program exited.\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Program exited.\n"); return 1; } @@ -1258,7 +1258,7 @@ PDB_disassemble(struct Parrot_Interp *interpreter, const char *command) pline = pline->next; if (!(pline)) { - fprintf(stderr,"Label number %li out of bounds.\n",label->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Label number %li out of bounds.\n",label->number); return; } @@ -1363,7 +1363,7 @@ PDB_load_source(struct Parrot_Interp *interpreter, const char *command) /* abort if fopen failed */ if (!file) { - fprintf(stderr,"Unable to load %s\n", f); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Unable to load %s\n", f); return; } @@ -1461,14 +1461,14 @@ PDB_list(struct Parrot_Interp *interpreter, const char *command) i = 1; while (line->next) { - fprintf(stderr,"%li ",pdb->file->list_line + i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%li ",pdb->file->list_line + i); /* If it has a label print it */ if (line->label) - fprintf(stderr,"L%li:\t",line->label->number); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"L%li:\t",line->label->number); c = pdb->file->source + line->source_offset; while (*c != '\n') - fprintf(stderr,"%c",*(c++)); - fprintf(stderr,"\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%c",*(c++)); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\n"); line = line->next; if (i++ == n) break; @@ -1501,7 +1501,7 @@ PDB_eval(struct Parrot_Interp *interpreter, const char *command) /* Find the opcode number */ op_number = interpreter->op_lib->op_code(buf, 1); if (op_number < 0) { - fprintf(stderr, "Invalid opcode '%s'\n", buf); + PIO_eprintf(interpreter, "Invalid opcode '%s'\n", buf); return; } /* Start generating the bytecode */ @@ -1619,7 +1619,7 @@ PDB_print_stack(struct Parrot_Interp *interpreter, const char *command) PDB_print_stack_pmc(interpreter, command); break; default: - fprintf(stderr,"Unknown argument \"%s\" to 'stack'\n", command); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Unknown argument \"%s\" to 'stack'\n", command); break; } } @@ -1638,14 +1638,14 @@ PDB_print_stack_int(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_INT_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"Integer stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Integer stack, frame %li, depth %li\n", i, depth); na(command); - PDB_print_int(&chunk->IReg[depth], atoi(command)); + PDB_print_int(interpreter, &chunk->IReg[depth], atoi(command)); } /* PDB_print_stack_num @@ -1661,14 +1661,14 @@ PDB_print_stack_num(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_NUM_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"Float stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Float stack, frame %li, depth %li\n", i, depth); na(command); - PDB_print_num(&chunk->NReg[depth], atoi(command)); + PDB_print_num(interpreter, &chunk->NReg[depth], atoi(command)); } /* PDB_print_stack_string @@ -1684,11 +1684,11 @@ PDB_print_stack_string(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_STR_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"String stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"String stack, frame %li, depth %li\n", i, depth); na(command); PDB_print_string(interpreter,&chunk->SReg[depth], atoi(command)); @@ -1707,11 +1707,11 @@ PDB_print_stack_pmc(struct Parrot_Interp *interpreter, const char *command) if (!chunk) { i = depth / FRAMES_PER_PMC_REG_CHUNK; - fprintf(stderr,"There are only %li frames\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"There are only %li frames\n",i); return; } - fprintf(stderr,"PMC stack, frame %li, depth %li\n", i, depth); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"PMC stack, frame %li, depth %li\n", i, depth); na(command); PDB_print_pmc(interpreter,&chunk->PReg[depth], atoi(command), NULL); @@ -1721,14 +1721,13 @@ static void dump_string(struct Parrot_Interp *interpreter, STRING* s) { if (s) { - fprintf(stderr,"\tBuflen =\t%12ld\n",s->buflen); - fprintf(stderr,"\tFlags =\t%12ld\n",s->flags); - fprintf(stderr,"\tBufused =\t%12ld\n",s->bufused); - fprintf(stderr,"\tStrlen =\t%12ld\n",s->strlen); - fprintf(stderr,"\tOffset =\t%12d\n", + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tBuflen =\t%12ld\n",s->buflen); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tFlags =\t%12ld\n",s->flags); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tBufused =\t%12ld\n",s->bufused); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tStrlen =\t%12ld\n",s->strlen); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tOffset =\t%12d\n", (char*) s->strstart - (char*) s->bufstart); - fprintf(stderr,"\tString =\t%s\n", - string_to_cstring(interpreter, s)); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"\tString =\t%S\n", s); } } @@ -1749,31 +1748,26 @@ PDB_print_user_stack(struct Parrot_Interp *interpreter, const char *command) switch (entry->entry_type) { case STACK_ENTRY_INT: - fprintf(stderr,"Integer\t=\t%8li\n",entry->entry.int_val); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Integer\t=\t%8vi\n",entry->entry.int_val); break; case STACK_ENTRY_FLOAT: - fprintf(stderr,"Float\t=\t%8.4f\n",entry->entry.num_val); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Float\t=\t%8.4vf\n",entry->entry.num_val); break; case STACK_ENTRY_STRING: - fprintf(stderr,"String =\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"String =\n"); dump_string(interpreter, entry->entry.string_val); break; case STACK_ENTRY_PMC: - fprintf(stderr,"PMC =\n"); - s = (entry->entry.pmc_val->vtable->get_string( - interpreter, entry->entry.pmc_val)); - - if (s) - fprintf(stderr,"%s\n", string_to_cstring(interpreter, (s))); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"PMC =\n%PS\n", entry->entry.pmc_val); break; case STACK_ENTRY_POINTER: - fprintf(stderr,"POINTER\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"POINTER\n"); break; case STACK_ENTRY_DESTINATION: - fprintf(stderr,"DESTINATION\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"DESTINATION\n"); break; default: - fprintf(stderr,"Invalid stack_entry_type!\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Invalid stack_entry_type!\n"); break; } } @@ -1812,11 +1806,11 @@ PDB_print(struct Parrot_Interp *interpreter, const char *command) switch (c) { case c_i: case c_int: - PDB_print_int(&interpreter->ctx.int_reg, regnum); + PDB_print_int(interpreter, &interpreter->ctx.int_reg, regnum); break; case c_n: case c_num: - PDB_print_num(&interpreter->ctx.num_reg, regnum); + PDB_print_num(interpreter, &interpreter->ctx.num_reg, regnum); break; case c_s: case c_str: @@ -1827,7 +1821,7 @@ PDB_print(struct Parrot_Interp *interpreter, const char *command) PDB_print_pmc(interpreter,&interpreter->ctx.pmc_reg, regnum, key); break; default: - fprintf(stderr, "Unrecognized print option: must be 'int', 'num', 'str', 'pmc', or a register\n"); + PIO_eprintf(interpreter, "Unrecognized print option: must be 'int', 'num', 'str', 'pmc', or a register\n"); } interpreter->DOD_block_level--; @@ -1837,7 +1831,7 @@ PDB_print(struct Parrot_Interp *interpreter, const char *command) * print the whole or a specific value of a integer register structure. */ void -PDB_print_int(struct IReg *int_reg, int regnum) +PDB_print_int(struct Parrot_Interp *interpreter, struct IReg *int_reg, int regnum) { int i,j = 0, k = NUM_REGISTERS; @@ -1846,10 +1840,10 @@ PDB_print_int(struct IReg *int_reg, int regnum) k = regnum + 1; } - fprintf(stderr,"Integer Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Integer Registers:\n"); for (i = j; i < k; i++) { - fprintf(stderr,"I%i =\t",i); - fprintf(stderr,"%11li\n",int_reg->registers[i]); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"I%i =\t",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%11vi\n",int_reg->registers[i]); } } @@ -1857,7 +1851,7 @@ PDB_print_int(struct IReg *int_reg, int regnum) * print the whole or a specific value of a float register structure. */ void -PDB_print_num(struct NReg *num_reg, int regnum) +PDB_print_num(struct Parrot_Interp *interpreter, struct NReg *num_reg, int regnum) { int i,j = 0, k = NUM_REGISTERS; @@ -1866,10 +1860,10 @@ PDB_print_num(struct NReg *num_reg, int regnum) k = regnum + 1; } - fprintf(stderr,"Float Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Float Registers:\n"); for (i = j; i < k; i++) { - fprintf(stderr,"N%i =\t",i); - fprintf(stderr,"%20.4f\n",num_reg->registers[i]); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"N%i =\t",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"%20.4f\n",num_reg->registers[i]); } } @@ -1888,9 +1882,9 @@ PDB_print_string(struct Parrot_Interp *interpreter, struct SReg *string_reg, k = regnum + 1; } - fprintf(stderr,"String Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"String Registers:\n"); for (i = j; i < k; i++) { - fprintf(stderr,"S%i =\n",i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"S%i =\n",i); dump_string(interpreter, string_reg->registers[i]); } } @@ -1901,16 +1895,12 @@ print_pmc(struct Parrot_Interp *interpreter, PMC* pmc) if (pmc && pmc->vtable) { STRING* s = pmc->vtable->name(interpreter, pmc); if (s) { - fprintf(stderr, " [%s]\n", string_to_cstring(interpreter, s)); - } - s = (pmc->vtable->get_string(interpreter, pmc)); - if (s) { - fprintf(stderr,"Stringified: %s\n", - string_to_cstring(interpreter, s)); + PIO_eprintf(interpreter, " [%S]\n", s); } + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"Stringified: %PS\n", pmc); } else { - fprintf(stderr, "\n"); + PIO_eprintf(interpreter, "\n"); } } @@ -1927,14 +1917,14 @@ PDB_print_pmc(struct Parrot_Interp *interpreter, struct PReg *pmc_reg, } if (regnum == -1) - fprintf(stderr,"PMC Registers:\n"); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"PMC Registers:\n"); for (i = j; i < k; i++) { PMC* pmc = pmc_reg->registers[i]; - fprintf(stderr,"P%i", i); + PIO_fprintf(interpreter, PIO_STDERR(interpreter),"P%i", i); if (key) trace_key_dump(interpreter, key); - fprintf(stderr," ="); + PIO_fprintf(interpreter, PIO_STDERR(interpreter)," ="); if (key) pmc = pmc->vtable->get_pmc_keyed(interpreter, pmc, key); print_pmc(interpreter, pmc); @@ -1947,17 +1937,17 @@ PDB_print_pmc(struct Parrot_Interp *interpreter, struct PReg *pmc_reg, void PDB_info(struct Parrot_Interp *interpreter) { - fprintf(stderr, "Total memory allocated = %d\n", + PIO_eprintf(interpreter, "Total memory allocated = %d\n", interpreter->memory_allocated); - fprintf(stderr, "DOD runs = %d\n", interpreter->dod_runs); - fprintf(stderr, "Collect runs = %d\n", interpreter->collect_runs); - fprintf(stderr, "Active PMCs = %d\n", interpreter->active_PMCs); - fprintf(stderr, "Active buffers = %d\n", interpreter->active_Buffers); - fprintf(stderr, "Total PMCs = %d\n", interpreter->total_PMCs); - fprintf(stderr, "Total buffers = %d\n", interpreter->total_Buffers); - fprintf(stderr, "Header allocations since last collect = %d\n", + PIO_eprintf(interpreter, "DOD runs = %d\n", interpreter->dod_runs); + PIO_eprintf(interpreter, "Collect runs = %d\n", interpreter->collect_runs); + PIO_eprintf(interpreter, "Active PMCs = %d\n", interpreter->active_PMCs); + PIO_eprintf(interpreter, "Active buffers = %d\n", interpreter->active_Buffers); + PIO_eprintf(interpreter, "Total PMCs = %d\n", interpreter->total_PMCs); + PIO_eprintf(interpreter, "Total buffers = %d\n", interpreter->total_Buffers); + PIO_eprintf(interpreter, "Header allocations since last collect = %d\n", interpreter->header_allocs_since_last_collect); - fprintf(stderr, "Memory allocations since last collect = %d\n", + PIO_eprintf(interpreter, "Memory allocations since last collect = %d\n", interpreter->mem_allocs_since_last_collect); } @@ -1968,23 +1958,24 @@ PDB_info(struct Parrot_Interp *interpreter) void PDB_help(const char *command) { - fprintf(stderr,"List of commands:\n"); - fprintf(stderr,"\tdisassemble -- disassemble the bytecode\n"); - fprintf(stderr,"\tload -- load a source code file\n"); - fprintf(stderr,"\tlist (l) -- list the source code file\n"); - fprintf(stderr,"\trun (r) -- run the programm\n"); - fprintf(stderr,"\tbreak (b) -- add a breakpoint\n"); - fprintf(stderr,"\twatch (w) -- add a watchpoint\n"); - fprintf(stderr,"\tdelete (d) -- delete a breakpoint\n"); - fprintf(stderr,"\tcontinue (c) -- continue the program execution\n"); - fprintf(stderr,"\tnext (n) -- run the next instruction\n"); - fprintf(stderr,"\teval (e) -- run an instruction\n"); - fprintf(stderr,"\ttrace (t) -- trace the next instruction\n"); - fprintf(stderr,"\tprint (p) -- print the interpreter registers\n"); - fprintf(stderr,"\tstack (s) -- examine the stack\n"); - fprintf(stderr,"\tinfo -- print interpreter information\n"); - fprintf(stderr,"\tquit (q) -- exit the debugger\n"); - fprintf(stderr,"\thelp (h) -- print this help\n\n"); + PIO_eprintf(NULL, "\ +List of commands:\n\ + disassemble -- disassemble the bytecode\n\ + load -- load a source code file\n\ + list (l) -- list the source code file\n\ + run (r) -- run the program\n\ + break (b) -- add a breakpoint\n\ + watch (w) -- add a watchpoint\n\ + delete (d) -- delete a breakpoint\n\ + continue (c) -- continue the program execution\n\ + next (n) -- run the next instruction\n\ + eval (e) -- run an instruction\n\ + trace (t) -- trace the next instruction\n\ + print (p) -- print the interpreter registers\n\ + stack (s) -- examine the stack\n\ + info -- print interpreter information\n\ + quit (q) -- exit the debugger\n\ + help (h) -- print this help\n\n"); } /* diff --git a/src/embed.c b/src/embed.c index 208711d391..2476f09dbb 100644 --- a/src/embed.c +++ b/src/embed.c @@ -36,9 +36,11 @@ Parrot_new(void) void Parrot_init(struct Parrot_Interp *interpreter, void* stacktop) +/* ^^^^^^^^^^^^^^ + XXX BD Do we really need this to be user-provided, or can + we set up our own in embed.c:Parrot_runcode()? +*/ { - /* This function currently unused, but is here in case we need it later. */ - if (!world_inited) { /* See comments in Parrot_new. */ world_inited = 1; @@ -97,13 +99,13 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) /* if we have stat(), get the actual file size so we can read it * in one chunk. */ if (stat(filename, &file_stat)) { - fprintf(stderr, "Parrot VM: Can't stat %s, code %i.\n", filename, + PIO_eprintf(interpreter, "Parrot VM: Can't stat %s, code %i.\n", filename, errno); return NULL; } if (!S_ISREG(file_stat.st_mode)) { - fprintf(stderr, "Parrot VM: %s is not a normal file.\n", filename); + PIO_eprintf(interpreter, "Parrot VM: %s is not a normal file.\n", filename); return NULL; } @@ -119,7 +121,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) #ifndef HAS_HEADER_SYSMMAN io = PIO_open(interpreter, filename, "<"); if (!io) { - fprintf(stderr, "Parrot VM: Can't open %s, code %i.\n", filename, + PIO_eprintf(interpreter, "Parrot VM: Can't open %s, code %i.\n", filename, errno); return NULL; } @@ -146,7 +148,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) if (NULL == program_code) { /* Whoops, out of memory. */ - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Could not allocate buffer to read packfile from PIO.\n"); return NULL; @@ -162,7 +164,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) realloc(program_code, program_size + chunk_size); if (NULL == program_code) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Could not reallocate buffer while reading packfile from PIO.\n"); return NULL; } @@ -171,7 +173,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) } if (read_result < 0) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Problem reading packfile from PIO.\n"); return NULL; } @@ -184,7 +186,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) fd = open(filename, O_RDONLY | O_BINARY); if (!fd) { - fprintf(stderr, "Parrot VM: Can't open %s, code %i.\n", filename, + PIO_eprintf(interpreter, "Parrot VM: Can't open %s, code %i.\n", filename, errno); return NULL; } @@ -193,14 +195,14 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) 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", + PIO_eprintf(interpreter, "Parrot VM: Can't read file %s, code %i.\n", filename, errno); return NULL; } #else /* HAS_HEADER_SYSMMAN */ - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: uncaught error occurred reading file or mmap not available.\n"); return NULL; @@ -214,7 +216,7 @@ Parrot_readbc(struct Parrot_Interp *interpreter, char *filename) if (!PackFile_unpack (interpreter, pf, (opcode_t *)program_code, program_size)) { - fprintf(stderr, "Parrot VM: Can't unpack packfile %s.\n", filename); + PIO_eprintf(interpreter, "Parrot VM: Can't unpack packfile %s.\n", filename); return NULL; } @@ -236,14 +238,14 @@ Parrot_loadbc(struct Parrot_Interp *interpreter, struct PackFile *pf) interpreter->code = pf; } -void -Parrot_setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv) +static void +setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv) { - int i; + INTVAL i; PMC *userargv; if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "*** Parrot VM: Setting up ARGV array in P0. Current argc: %d ***\n", argc); } @@ -258,7 +260,7 @@ Parrot_setup_argv(struct Parrot_Interp *interpreter, int argc, char ** argv) 0, BUFFER_external_FLAG, 0); if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { - fprintf(stderr, "\t%d: %s\n", i, argv[i]); + PIO_eprintf(interpreter, "\t%vd: %s\n", i, argv[i]); } userargv->vtable->push_string(interpreter, userargv, arg); @@ -272,19 +274,19 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) /* Debugging mode nonsense. */ if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { - fprintf(stderr, "*** Parrot VM: Debugging enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Debugging enabled. ***\n"); if (Interp_flags_TEST(interpreter, PARROT_BOUNDS_FLAG)) { - fprintf(stderr, "*** Parrot VM: Bounds checking enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Bounds checking enabled. ***\n"); } if (Interp_flags_TEST(interpreter, PARROT_PREDEREF_FLAG)) { - fprintf(stderr, "*** Parrot VM: Predereferencing enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Predereferencing enabled. ***\n"); } if (Interp_flags_TEST(interpreter, PARROT_JIT_FLAG)) { - fprintf(stderr, "*** Parrot VM: JIT enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: JIT enabled. ***\n"); } if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) { - fprintf(stderr, "*** Parrot VM: Tracing enabled. ***\n"); + PIO_eprintf(interpreter, "*** Parrot VM: Tracing enabled. ***\n"); } } @@ -293,7 +295,7 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) /* No JIT here--make sure they didn't ask for it. */ if (Interp_flags_TEST(interpreter, PARROT_JIT_FLAG)) { - fprintf(stderr, + PIO_fprintf(interpreter, PIO_STDERR(interpreter), "Parrot VM: Platform " JIT_ARCHNAME " is not JIT-capable.\n"); exit(1); } @@ -303,7 +305,7 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) /* Set up @ARGS (or whatever this language calls it). XXX Should this be Array or PerlArray? */ - Parrot_setup_argv(interpreter, argc, argv); + setup_argv(interpreter, argc, argv); /* Let's kick the tires and light the fires--call interpreter.c:runops. */ runops(interpreter, interpreter->code, 0); @@ -313,15 +315,15 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) */ if (interpreter->profile != NULL) { - unsigned int j; - int op_count = 0; - int call_count = 0; + UINTVAL j; + UINTVAL op_count = 0; + UINTVAL call_count = 0; FLOATVAL sum_time = 0.0; - printf("\n\n"); - printf(" OPERATION PROFILE \n\n"); - printf(" CODE OP FULL NAME CALLS TOTAL TIME AVG TIME\n"); - printf(" ----- ------------ ------ ---------- ----------\n"); + PIO_printf(interpreter, "\n\n"); + PIO_printf(interpreter, " OPERATION PROFILE \n\n"); + PIO_printf(interpreter, " CODE OP FULL NAME CALLS TOTAL TIME AVG TIME\n"); + PIO_printf(interpreter, " ----- ------------ ------ ---------- ----------\n"); for (j = 0; j < interpreter->op_count; j++) { if (interpreter->profile[j].numcalls > 0) { @@ -329,41 +331,41 @@ Parrot_runcode(struct Parrot_Interp *interpreter, int argc, char *argv[]) call_count += interpreter->profile[j].numcalls; sum_time += interpreter->profile[j].time; - printf(" %5u %-12s %6ld %10f %10f\n", j, + PIO_printf(interpreter, " %5vu %-12s %6vu %10vf %10vf\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 + (FLOATVAL)(interpreter->profile[j].time / + (FLOATVAL)interpreter->profile[j].numcalls) ); } } - printf(" ----- ------------ ------ ---------- ----------\n"); - printf(" %5d %-12s %6d %10f %10f\n", + PIO_printf(interpreter, " ----- ------------ ------ ---------- ----------\n"); + PIO_printf(interpreter, " %5vu %-12s %6vu %10vf %10vf\n", op_count, "", call_count, sum_time, - sum_time / (FLOATVAL)call_count + (FLOATVAL)(sum_time / (FLOATVAL)call_count) ); } if (Interp_flags_TEST(interpreter, PARROT_DEBUG_FLAG)) { /* Give the souls brave enough to activate debugging an earful * about GC. */ - fprintf(stderr, "\ + PIO_eprintf(interpreter, "\ *** Parrot VM: Dumping GC info ***\n\ -\tTotal memory allocated: %u\n\ -\tTotal DOD runs: %u\n\ -\tTotal collector runs: %u\n\ -\tActive PMCs: %u\n\ -\tActive buffers: %u\n\ -\tTotal PMCs: %u\n\ -\tTotal buffers: %u\n\ +\tTotal memory allocated: %p\n\ +\tTotal DOD runs: %p\n\ +\tTotal collector runs: %p\n\ +\tActive PMCs: %p\n\ +\tActive buffers: %p\n\ +\tTotal PMCs: %p\n\ +\tTotal buffers: %p\n\ \tSince last collection:\n\ -\t\tHeader allocations: %u\n\ -\t\tMemory allocations: %u\n\ +\t\tHeader allocations: %p\n\ +\t\tMemory allocations: %p\n\ \n", interpreter->memory_allocated, interpreter->dod_runs, @@ -382,7 +384,7 @@ void Parrot_destroy(struct Parrot_Interp *interp) { /* XXX Leaks tons of memory. */ - free(interp); + mem_sys_free(interp); } /* XXX Doesn't handle arguments with spaces */ @@ -448,11 +450,11 @@ Parrot_disassemble(struct Parrot_Interp *interpreter) while (line->next) { /* If it has a label print it */ if (line->label) - printf("L%li:\t", line->label->number); + PIO_printf(interpreter, "L%li:\t", line->label->number); c = pdb->file->source + line->source_offset; while (*c != '\n' && c) - printf("%c", *(c++)); - printf("\n"); + PIO_printf(interpreter, "%c", *(c++)); + PIO_printf(interpreter, "\n"); line = line->next; } return; diff --git a/src/exceptions.c b/src/exceptions.c index 9b2cfecbdb..b530651da7 100644 --- a/src/exceptions.c +++ b/src/exceptions.c @@ -28,35 +28,48 @@ internal_exception(int exitcode, const char *format, ...) /* Panic handler */ -#define dumpcore() printf("Sorry, coredump is not yet implemented for this platform.\n\n"); exit(1); +#define dumpcore() PIO_printf(interpreter, "Sorry, coredump is not yet implemented for this platform.\n\n"); exit(1); void do_panic(struct Parrot_Interp *interpreter, const char *message, const char *file, int line) { - printf("Parrot VM: PANIC: %s!\n", message ? message : "(no message available)"); - printf("C file %s, line %d\n", file ? file : "(file name not available)", line); - printf("Parrot file %s, ", "(not available)"); - if (interpreter) - printf("line %d\n", interpreter->current_line); - else - printf("line ((not available)\n"); - printf("\n\ + /* Note: we can't format any floats in here--Parrot_sprintf + ** may panic because of floats. + */ + + PIO_printf(interpreter, "\ +Parrot VM: PANIC: %s!\n\ +C file %s, line %d\n\ +Parrot file %s, line %d\n\ +\n\ We highly suggest you notify the Parrot team if you have not been working on \n\ Parrot. Use bugs6.perl.org or send an e-mail to perl6-internals@perl.org. \n\ Include the entire text of this error message and the text of the script that \n\ generated the error. If you've made any modifications to Parrot, please \n\ -describe them as well.\n"); - printf("Version : %s\n", PARROT_VERSION); - printf("Configured : %s\n", PARROT_CONFIG_DATE); - printf("Architecture: %s\n", PARROT_ARCHNAME); - printf("JIT Capable : %s\n", (JIT_CAPABLE ? "Yes" : "No")); - if (interpreter) - printf("Interp Flags: 0x%x\n", interpreter->flags); - else - printf("Interp Flags: (not available)\n"); - printf("Exceptions : (missing from core)\n"); - printf("\nDumping core...\n\n"); +describe them as well.\n\ +\n\ +Version : %s\n\ +Configured : %s\n\ +Architecture: %s\n\ +JIT Capable : %s\n\ +Interp Flags: %#x\n\ +Exceptions : %s\n\ +\n\ +Dumping Core...\n", + message ? message : "(not available)", + line, + file ? file : "(not available)", + interpreter ? string_to_cstring(interpreter, interpreter->current_file) : "(not available)", + interpreter ? (int)interpreter->current_line : 0, + PARROT_VERSION, + PARROT_CONFIG_DATE, + PARROT_ARCHNAME, + JIT_CAPABLE ? "Yes" : "No", + interpreter ? interpreter->flags : -1, + "(missing from core)" + ); + dumpcore(); } diff --git a/src/hash.c b/src/hash.c index 2b4e3270ba..39eb80c108 100644 --- a/src/hash.c +++ b/src/hash.c @@ -104,7 +104,8 @@ void dump_hash(Interp *interpreter, HASH *hash) { HashIndex i; - fprintf(stderr, "Hashtable[" INTVAL_FMT "/" INTVAL_FMT "]\n", + PIO_fprintf(interpreter, PIO_STDERR(interpreter), + "Hashtable[%vd/%vd]\n", hash->entries, hash->max_chain + 1); /* Iterate one past the end of the hashtable, so we can use the @@ -115,13 +116,13 @@ dump_hash(Interp *interpreter, HASH *hash) if (i > hash->max_chain) bucket = getBucket(hash, hash->free_list); else bucket = lookupBucket(hash, i); if (bucket == NULL) continue; - fprintf(stderr, " Bucket " INTVAL_FMT ": ", i); + PIO_eprintf(interpreter, " Bucket %vd: ", i); while (bucket) { - fprintf(stderr, "type(%d)", bucket->value.type); + PIO_eprintf(interpreter, "type(%d)", bucket->value.type); bucket = getBucket(hash, bucket->next); - if (bucket) fprintf(stderr, " -> "); + if (bucket) PIO_eprintf(interpreter, " -> "); } - fprintf(stderr, "\n"); + PIO_eprintf(interpreter, "\n"); } } @@ -335,7 +336,7 @@ hash_size(Interp *interpreter, HASH *hash) return hash->entries; } else { - fprintf(stderr, "*** hash_size asked to check a NULL hash\n"); + PIO_eprintf(interpreter, "*** hash_size asked to check a NULL hash\n"); return 0; } } diff --git a/src/interpreter.c b/src/interpreter.c index 4bd9590e94..cbccba6215 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -22,8 +22,6 @@ # include "parrot/oplib/core_ops_cg.h" #endif - - /*=for api interpreter runops_generic * TODO: Not really part of the API, but here's the docs. * Generic runops, which takes a function pointer for the core. diff --git a/src/jit.c b/src/jit.c index 0b5b843939..0109ef46dc 100644 --- a/src/jit.c +++ b/src/jit.c @@ -376,36 +376,36 @@ END_SECTION:cur_section->end = cur_op; #if JIT_DEBUG cur_section = optimizer->sections; while (cur_section) { - fprintf(stderr, "\nSection:\n"); - fprintf(stderr, "%s\n", (cur_section->type) ? "JITTED" : "NOT JITTED"); - fprintf(stderr, "\tbegin:\t0x%x\t(%li)\n", - (unsigned int)cur_section->begin, *cur_section->begin); - fprintf(stderr, "\tend:\t0x%x\t(%li)\n", - (unsigned int)cur_section->end, *cur_section->end); - fprintf(stderr, "\tInt register count:\t"); + PIO_eprintf(interpreter, "\nSection:\n"); + PIO_eprintf(interpreter, "%s\n", (cur_section->type) ? "JITTED" : "NOT JITTED"); + PIO_eprintf(interpreter, "\tbegin:\t%#p\t(%Ou)\n", + cur_section->begin, *cur_section->begin); + PIO_eprintf(interpreter, "\tend:\t%#p\t(%Ou)\n", + cur_section->end, *cur_section->end); + PIO_eprintf(interpreter, "\tInt register count:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->int_reg_count[i]); - fprintf(stderr, "\n\tInt register usage:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->int_reg_count[i]); + PIO_eprintf(interpreter, "\n\tInt register usage:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->int_reg_usage[i]); - fprintf(stderr, "\n\tInt register direction:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->int_reg_usage[i]); + PIO_eprintf(interpreter, "\n\tInt register direction:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", (int)cur_section->int_reg_dir[i]); - fprintf(stderr, "\n\tInt registers used:\t%i\n", + PIO_eprintf(interpreter, "%i ", (int)cur_section->int_reg_dir[i]); + PIO_eprintf(interpreter, "\n\tInt registers used:\t%i\n", cur_section->int_registers_used); - fprintf(stderr, "\tFloat register count:\t"); + PIO_eprintf(interpreter, "\tFloat register count:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->float_reg_count[i]); - fprintf(stderr, "\n\tFloat register usage:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->float_reg_count[i]); + PIO_eprintf(interpreter, "\n\tFloat register usage:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", cur_section->float_reg_usage[i]); - fprintf(stderr, "\n\tFloat register direction:\t"); + PIO_eprintf(interpreter, "%i ", cur_section->float_reg_usage[i]); + PIO_eprintf(interpreter, "\n\tFloat register direction:\t"); for (i = 0; i < NUM_REGISTERS; i++) - fprintf(stderr, "%i ", (int)cur_section->float_reg_dir[i]); - fprintf(stderr, "\n\tFloat Registers used:\t%i\n", + PIO_eprintf(interpreter, "%i ", (int)cur_section->float_reg_dir[i]); + PIO_eprintf(interpreter, "\n\tFloat Registers used:\t%i\n", cur_section->float_registers_used); - fprintf(stderr, "\tJit opcodes:\t%i\n", cur_section->jit_op_count); - fprintf(stderr, "\tTotal opcodes:\t%i\n", cur_section->op_count); + PIO_eprintf(interpreter, "\tJit opcodes:\t%u\n", cur_section->jit_op_count); + PIO_eprintf(interpreter, "\tTotal opcodes:\t%u\n", cur_section->op_count); cur_section = cur_section->next; } #endif diff --git a/src/malloc.c b/src/malloc.c index ca9ca25f34..44e0e0a5e5 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -4703,30 +4703,30 @@ void mSTATs() { CHUNK_SIZE_T free, reserved, committed; vminfo (&free, &reserved, &committed); - fprintf(stderr, "free bytes = %10lu\n", + PIO_eprintf(NULL, "free bytes = %10lu\n", free); - fprintf(stderr, "reserved bytes = %10lu\n", + PIO_eprintf(NULL, "reserved bytes = %10lu\n", reserved); - fprintf(stderr, "committed bytes = %10lu\n", + PIO_eprintf(NULL, "committed bytes = %10lu\n", committed); } #endif - fprintf(stderr, "max system bytes = %10lu\n", + PIO_eprintf(NULL, "max system bytes = %10lu\n", (CHUNK_SIZE_T)(mi.usmblks)); - fprintf(stderr, "system bytes = %10lu\n", + PIO_eprintf(NULL, "system bytes = %10lu\n", (CHUNK_SIZE_T)(mi.arena + mi.hblkhd)); - fprintf(stderr, "in use bytes = %10lu\n", + PIO_eprintf(NULL, "in use bytes = %10lu\n", (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd)); #ifdef WIN32 { CHUNK_SIZE_T kernel, user; if (cpuinfo (TRUE, &kernel, &user)) { - fprintf(stderr, "kernel ms = %10lu\n", + PIO_eprintf(NULL, "kernel ms = %10lu\n", kernel); - fprintf(stderr, "user ms = %10lu\n", + PIO_eprintf(NULL, "user ms = %10lu\n", user); } } @@ -5033,7 +5033,7 @@ static void *sbrk (long size) { static region_list_entry *g_last; void *result = (void *) MORECORE_FAILURE; #ifdef TRACE - printf ("sbrk %d\n", size); + PIO_printf (NULL, "sbrk %d\n", size); #endif #if defined (USE_MALLOC_LOCK) && defined (NEEDED) /* Wait for spin lock */ @@ -5090,7 +5090,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) base_committed % g_pagesize == 0); #ifdef TRACE - printf ("Commit %p %d\n", base_committed, remaining_commit_size); + PIO_printf (NULL, "Commit %p %d\n", base_committed, remaining_commit_size); #endif /* Adjust the regions commit top */ g_last->top_committed = (char *) base_committed + remaining_commit_size; @@ -5116,7 +5116,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) memory_info.BaseAddress % g_pagesize == 0); #ifdef TRACE - printf ("Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize, + PIO_printf (NULL, "Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize, memory_info.State == MEM_FREE ? "FREE": (memory_info.State == MEM_RESERVE ? "RESERVED": (memory_info.State == MEM_COMMIT ? "COMMITTED": "?"))); @@ -5160,7 +5160,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) base_reserved % g_regionsize == 0); #ifdef TRACE - printf ("Reserve %p %d\n", base_reserved, reserve_size); + PIO_printf (NULL, "Reserve %p %d\n", base_reserved, reserve_size); #endif /* Did we get contiguous memory? */ if (contiguous) { @@ -5198,7 +5198,7 @@ static void *sbrk (long size) { /* Assert postconditions */ assert ((unsigned) base_committed % g_pagesize == 0); #ifdef TRACE - printf ("Commit %p %d\n", base_committed, commit_size); + PIO_printf (NULL, "Commit %p %d\n", base_committed, commit_size); #endif /* Adjust the regions commit top */ g_last->top_committed = (char *) base_committed + commit_size; @@ -5226,7 +5226,7 @@ static void *sbrk (long size) { if (! rc) goto sbrk_exit; #ifdef TRACE - printf ("Release %p %d\n", base_reserved, release_size); + PIO_printf (NULL, "Release %p %d\n", base_reserved, release_size); #endif } /* Adjust deallocation size */ @@ -5252,7 +5252,7 @@ static void *sbrk (long size) { if (! rc) goto sbrk_exit; #ifdef TRACE - printf ("Decommit %p %d\n", base_committed, decommit_size); + PIO_printf (NULL, "Decommit %p %d\n", base_committed, decommit_size); #endif } /* Adjust deallocation size and regions commit and allocate top */ @@ -5295,7 +5295,7 @@ static void *mmap (void *ptr, long size, long prot, long type, long handle, long static long g_pagesize; static long g_regionsize; #ifdef TRACE - printf ("mmap %d\n", size); + PIO_printf (NULL, "mmap %d\n", size); #endif #if defined (USE_MALLOC_LOCK) && defined (NEEDED) /* Wait for spin lock */ @@ -5319,7 +5319,7 @@ static void *mmap (void *ptr, long size, long prot, long type, long handle, long /* Assert postconditions */ assert ((unsigned) ptr % g_regionsize == 0); #ifdef TRACE - printf ("Commit %p %d\n", ptr, size); + PIO_printf (NULL, "Commit %p %d\n", ptr, size); #endif mmap_exit: #if defined (USE_MALLOC_LOCK) && defined (NEEDED) @@ -5335,7 +5335,7 @@ static long munmap (void *ptr, long size) { static long g_regionsize; int rc = MUNMAP_FAILURE; #ifdef TRACE - printf ("munmap %p %d\n", ptr, size); + PIO_printf (NULL, "munmap %p %d\n", ptr, size); #endif #if defined (USE_MALLOC_LOCK) && defined (NEEDED) /* Wait for spin lock */ @@ -5355,7 +5355,7 @@ static long munmap (void *ptr, long size) { goto munmap_exit; rc = 0; #ifdef TRACE - printf ("Release %p %d\n", ptr, size); + PIO_printf (NULL, "Release %p %d\n", ptr, size); #endif munmap_exit: #if defined (USE_MALLOC_LOCK) && defined (NEEDED) diff --git a/src/misc.c b/src/misc.c index 4fd107f7e5..223fe673e9 100644 --- a/src/misc.c +++ b/src/misc.c @@ -3,493 +3,46 @@ * CVS Info * $Id$ * Overview: - * Miscellaneous functions + * Miscellaneous functions, mainly the Parrot_sprintf family * Data Structure and Algorithms: + * Uses a generalized formatting algorithm (spf_render.c) with + * a specialized vtable (spf_vtable.c) to handle argument extraction. * History: + * This was once a simple, vararg-based implementation that existed + * completely within this file. When the file grew to be nearly 1,000 + * lines long, I split it into three. --BD * Notes: - * References: + * References: misc.h, spf_vtable.c, spf_render.c */ -#include "parrot/parrot.h" - -#include - -typedef long HUGEINTVAL; -typedef unsigned long UHUGEINTVAL; - -typedef struct spfinfo_t { - UINTVAL flags; - UINTVAL width; - UINTVAL prec; - UINTVAL type; - UINTVAL phase; -} *SpfInfo; - -#define cstr2pstr(cstr) string_make(interpreter, cstr, strlen(cstr), NULL, 0, NULL) -#define char2pstr(ch) string_make(interpreter, &ch, 1, NULL, 0, NULL) - -#define PHASE_FLAGS 0 -#define PHASE_WIDTH 1 -#define PHASE_PREC 2 -#define PHASE_TYPE 3 -#define PHASE_TERM 4 -#define PHASE_DONE 5 - -#define FLAG_MINUS 1 -#define FLAG_PLUS 2 -#define FLAG_ZERO 4 -#define FLAG_SPACE 8 -#define FLAG_SHARP 16 - -#define SIZE_REG 0 -#define SIZE_SHORT 1 -#define SIZE_LONG 2 -#define SIZE_HUGE 3 -#define SIZE_XVAL 4 - -#define GetInt(targ, whichone) \ - switch(whichone) { \ - case SIZE_REG: \ - targ=(HUGEINTVAL)(int)va_arg(*args, int); \ - break; \ - case SIZE_SHORT: /* "'short int' is promoted to 'int' when passed through '...'" */ \ - targ=(HUGEINTVAL)(short)va_arg(*args, int); \ - break; \ - case SIZE_LONG: \ - targ=(HUGEINTVAL)(long)va_arg(*args, long); \ - break; \ - case SIZE_HUGE: \ - targ=(HUGEINTVAL)(long /*long*/)va_arg(*args, long /*long*/); \ - break; \ - case SIZE_XVAL: \ - targ=(HUGEINTVAL)(INTVAL)va_arg(*args, INTVAL); \ - break; \ - } - -#define GetUInt(targ, whichone) \ - switch(whichone) { \ - case SIZE_REG: \ - targ=(UHUGEINTVAL)(unsigned int)va_arg(*args, unsigned int); \ - break; \ - case SIZE_SHORT: /* short int promoted HLAGHLAGHLAGH. See note above */ \ - targ=(UHUGEINTVAL)(unsigned short)va_arg(*args, int); \ - break; \ - case SIZE_LONG: \ - targ=(UHUGEINTVAL)(unsigned long)va_arg(*args, unsigned long); \ - break; \ - case SIZE_HUGE: \ - targ=(UHUGEINTVAL)(unsigned long /*long*/)va_arg(*args, unsigned long /*long*/); \ - break; \ - case SIZE_XVAL: \ - targ=(UHUGEINTVAL)(UINTVAL)va_arg(*args, UINTVAL); \ - break; \ - } - -/* -void int_to_str(char *, char *, HUGEINTVAL, INTVAL ); -*/ - -void gen_sprintf_call(char *, char *, SpfInfo, char); - -static void -uint_to_str(char *buf1, char *buf2, UHUGEINTVAL num, char base) -{ - int i = 0, cur2; - char cur; - - do { - cur = (char)(num % base); - - if (cur < 10) { - buf2[i] = (char)('0' + cur); - } - else { - buf2[i] = (char)('a' + cur - 10); - } - - i++; - } while (num /= base); - - cur2 = i; - - for (i = 0; i <= cur2; i++) { - buf1[i] = buf2[cur2 - i]; - } -} - -static void -int_to_str(char *buf1, char *buf2, HUGEINTVAL num, char base) -{ - INTVAL neg; - int i = 0, cur2; - char cur; - - if (num < 0) { - neg = 1; - num = -num; - } - else { - neg = 0; - } - - do { - cur = (char)(num % base); - - if (cur < 10) { - buf2[i] = (char)('0' + cur); - } - else { - buf2[i] = (char)('a' + cur - 10); - } - - i++; - } while (num /= base); - - if (neg) { - buf2[i++] = '-'; - } - - cur2 = i; - - for (i = 0; i < cur2; i++) { - buf1[i] = buf2[cur2 - i - 1]; - } +#define IN_SPF_SYSTEM - buf1[i] = 0; -} - -static void -Pad_it(SpfInfo info, char *buf) -{ - int i; - int len = strlen(buf); - int howmuch = info->width - len; - - if (!info->width || howmuch == 0) { - return; - } - else if (howmuch < 0) { - memmove(buf, buf - howmuch, (size_t)(len + howmuch)); - } - else if (info->flags & FLAG_MINUS) { /* left-align */ - for (i = 0; i < howmuch; i++) { - buf[i + len] = ' '; - } - - buf[i + len] = 0; - } - else { /* right-align */ - memmove(buf + howmuch, buf, (size_t)len); - - for (i = 0; i < howmuch; i++) { - buf[i] = ' '; - } - } -} - -void -gen_sprintf_call(char *buf, char *buf2, SpfInfo info, char thingy) -{ - int i = 0; - buf[i++] = '%'; - - if (info->flags) { - if (info->flags & FLAG_MINUS) { - buf[i++] = '-'; - } - if (info->flags & FLAG_PLUS) { - buf[i++] = '+'; - } - if (info->flags & FLAG_ZERO) { - buf[i++] = '0'; - } - if (info->flags & FLAG_SPACE) { - buf[i++] = ' '; - } - if (info->flags & FLAG_SHARP) { - buf[i++] = '#'; - } - } - - if (info->width) { - uint_to_str(buf + i, buf2, info->width, 10); - i = strlen(buf); - } - - if (info->prec) { - buf[i++] = '.'; - uint_to_str(buf + i, buf2, info->prec, 10); - i = strlen(buf); - } +#include "parrot/parrot.h" - buf[i++] = thingy; - buf[i] = 0; -} +/* All the other sprintf variants are implemented in terms of + * Parrot_vsprintf_s. + * + * NAMING CONVENTION: + * Parrot_v?n?sprintf - a (nearly) drop-in replacement for v?n?sprintf. + * Parrot_v?sprintf_c - takes a C-string format, returns a Parrot string. + * Parrot_v?sprintf_s - takes a Parrot string format, returns a Parrot string. + * + * So the _ means "returns Parrot string" and the other letter indicates the + * type for the format. :^) + */ STRING * -Parrot_vsprintf_s(struct Parrot_Interp *interpreter, STRING *pat, - va_list *args) +Parrot_vsprintf_s(struct Parrot_Interp *interpreter, STRING *pat, va_list args) { - INTVAL i; - STRING *targ = NULL; - register char *t1 = mem_sys_allocate(4096); - register char *t2 = mem_sys_allocate(4096); - - for (i = 0; i < (INTVAL)string_length(pat); i++) { - if (string_ord(pat, i) == '%') { - if (string_ord(pat, i + 1) == '%') { - i++; - } - else { - /* hoo boy, here we go... */ - char *chptr; - STRING *string; - PMC *pmc; - double dbl; - register HUGEINTVAL theint = 0; - register UHUGEINTVAL theuint = 0; - - struct spfinfo_t info = { 0, 0, 0, 0, 0 }; - - for (i++; i < (INTVAL)string_length(pat) - && info.phase != PHASE_DONE; i++) { - INTVAL ch = string_ord(pat, i); - - switch (info.phase) { - /*@fallthrough@ */ case PHASE_FLAGS: - switch (ch) { - case '-': - info.flags |= FLAG_MINUS; - break; - - case '+': - info.flags |= FLAG_PLUS; - break; - - case '0': - info.flags |= FLAG_ZERO; - break; - - case ' ': - info.flags |= FLAG_SPACE; - break; - - case '#': - info.flags |= FLAG_SHARP; - break; - - default: - info.phase = PHASE_WIDTH; - } - - - /*@fallthrough@ */ case PHASE_WIDTH: - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '8': - case '9': - info.width *= 10; - info.width += ch - '0'; - break; - - case '.': - info.phase = PHASE_PREC; - continue; - - default: - info.phase = PHASE_PREC; - } - - /*@fallthrough@ */ case PHASE_PREC: - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '8': - case '9': - info.prec *= 10; - info.prec += ch - '0'; - continue; - - default: - info.phase = PHASE_TYPE; - } - - /*@fallthrough@ */ case PHASE_TYPE: - switch (ch) { - case 'h': - info.type = SIZE_SHORT; - continue; - - case 'l': - info.type = SIZE_LONG; - continue; - - case 'H': - info.type = SIZE_HUGE; - continue; - - case 'v': - info.type = SIZE_XVAL; - continue; - - default: - info.phase = PHASE_TERM; - } - - - /*@fallthrough@ */ case PHASE_TERM: - switch (ch) { - /* INTEGERS */ - case 'c': - targ = string_concat(interpreter, targ, - char2pstr(ch), 0); - break; - - case 'd': - case 'i': - GetInt(theint, info.type); - int_to_str(t1, t2, theint, 10); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'o': - GetInt(theint, info.type); - int_to_str(t1, t2, theint, 8); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'x': - GetInt(theint, info.type); - int_to_str(t1, t2, theint, 16); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'u': - GetUInt(theuint, info.type); - uint_to_str(t1, t2, theuint, 10); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - case 'p': - chptr = va_arg(*args, void *); - int_to_str(t1, t2, (HUGEINTVAL)chptr, 16); - targ = string_concat(interpreter, targ, - cstr2pstr(t1), 0); - break; - - /* FLOATS - We cheat on these and use the system sprintf. */ - case 'e': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'e'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'E': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'E'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'f': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'f'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'g': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'g'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - case 'G': - dbl = va_arg(*args, double); - gen_sprintf_call(t1, t2, &info, 'G'); - sprintf(t2, t1, dbl); - targ = string_concat(interpreter, targ, - cstr2pstr(t2), 0); - break; - - /* STRINGS */ - case 's': - chptr = va_arg(*args, char *); - if (info.prec) - targ = string_concat(interpreter, targ, - string_make(interpreter, chptr, - info.prec, NULL,0,NULL),0); - else - targ = string_concat(interpreter, targ, - cstr2pstr(chptr), 0); - break; - - case 'S': - string = va_arg(*args, STRING *); - if (info.prec) - targ = string_concat(interpreter, targ, - string_chopn(string, -info.prec), 0); - else - targ = string_concat(interpreter, targ, string, 0); - break; - - case 'P': - pmc = va_arg(*args, PMC *); - targ = - string_concat(interpreter, targ, - string_chopn( - pmc->vtable->get_string(interpreter, pmc), - -info.prec), - 0); - break; - - } - - info.phase = PHASE_DONE; - } - } - } - - i--; - } - else { - STRING *substr = NULL; - string_substr(interpreter, pat, i, 1, &substr); - targ = string_concat(interpreter, targ, substr, 0); - } - } - - mem_sys_free(t1); - mem_sys_free(t2); + SPRINTF_OBJ obj = va_core; + obj.data = &args; - return targ; + return Parrot_sprintf_format(interpreter, pat, &obj); } - STRING * Parrot_vsprintf_c(struct Parrot_Interp *interpreter, const char *pat, - va_list *args) + va_list args) { STRING *realpat = string_make(interpreter, pat, strlen(pat), NULL, 0, NULL); @@ -499,18 +52,18 @@ Parrot_vsprintf_c(struct Parrot_Interp *interpreter, const char *pat, void Parrot_vsprintf(struct Parrot_Interp *interpreter, char *targ, const char *pat, - va_list *args) + va_list args) { STRING *ret = Parrot_vsprintf_c(interpreter, pat, args); -/* string_transcode(interpreter, ret, NULL, NULL, &ret);*/ + string_transcode(interpreter, ret, NULL, NULL, &ret); memcpy(targ, ret->strstart, ret->bufused); - targ[ret->bufused + 1] = 00; + targ[ret->bufused + 1] = '\0'; } void Parrot_vsnprintf(struct Parrot_Interp *interpreter, char *targ, - UINTVAL len, const char *pat, va_list *args) + size_t len, const char *pat, va_list args) { STRING *ret = Parrot_vsprintf_c(interpreter, pat, args); string_transcode(interpreter, ret, NULL, NULL, &ret); @@ -531,7 +84,7 @@ Parrot_sprintf_s(struct Parrot_Interp *interpreter, STRING *pat, ...) va_start(args, pat); - ret = Parrot_vsprintf_s(interpreter, pat, &args); + ret = Parrot_vsprintf_s(interpreter, pat, args); va_end(args); @@ -546,7 +99,7 @@ Parrot_sprintf_c(struct Parrot_Interp *interpreter, const char *pat, ...) va_start(args, pat); - ret = Parrot_vsprintf_c(interpreter, pat, &args); + ret = Parrot_vsprintf_c(interpreter, pat, args); va_end(args); @@ -561,24 +114,33 @@ Parrot_sprintf(struct Parrot_Interp *interpreter, char *targ, const char *pat, va_start(args, pat); - Parrot_vsprintf(interpreter, targ, pat, &args); + Parrot_vsprintf(interpreter, targ, pat, args); va_end(args); } void -Parrot_snprintf(struct Parrot_Interp *interpreter, char *targ, UINTVAL len, +Parrot_snprintf(struct Parrot_Interp *interpreter, char *targ, size_t len, const char *pat, ...) { va_list args; va_start(args, pat); - Parrot_vsnprintf(interpreter, targ, len, pat, &args); + Parrot_vsnprintf(interpreter, targ, len, pat, args); va_end(args); } +STRING * +Parrot_psprintf(struct Parrot_Interp *interpreter, STRING *pat, PMC * ary) +{ + SPRINTF_OBJ obj = pmc_core; + obj.data = ary; + + return Parrot_sprintf_format(interpreter, pat, &obj); +} + /* * Local variables: * c-indentation-style: bsd diff --git a/src/packdump.c b/src/packdump.c index f930d61f04..83c3bb2051 100644 --- a/src/packdump.c +++ b/src/packdump.c @@ -18,28 +18,28 @@ PackFile_dump(struct PackFile *self) { size_t i; - printf("FIXUP => {\n"); + PIO_printf(NULL, "FIXUP => {\n"); PackFile_FixupTable_dump(self->fixup_table); - printf("},\n"); + PIO_printf(NULL, "},\n"); - printf("CONST => [\n"); + PIO_printf(NULL, "CONST => [\n"); PackFile_ConstTable_dump(self->const_table); - printf("],\n"); + PIO_printf(NULL, "],\n"); - printf("BCODE => [ # %ld bytes", (long)self->byte_code_size); + PIO_printf(NULL, "BCODE => [ # %ld bytes", (long)self->byte_code_size); for (i = 0; i < self->byte_code_size / sizeof(opcode_t); i++) { if (i % 8 == 0) { - printf("\n %08lx: ", (unsigned long)i * sizeof(opcode_t)); + PIO_printf(NULL, "\n %08lx: ", (unsigned long)i * sizeof(opcode_t)); } - printf("%08lx ", (unsigned long)self->byte_code[i]); + PIO_printf(NULL, "%08lx ", (unsigned long)self->byte_code[i]); } - printf("\n]\n"); + PIO_printf(NULL, "\n]\n"); return; } @@ -57,12 +57,12 @@ PackFile_ConstTable_dump(struct PackFile_ConstTable *self) opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_dump: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_dump: self == NULL!\n"); return; } for (i = 0; i < self->const_count; i++) { - printf(" # %ld:\n", (long)i); + PIO_printf(NULL, " # %ld:\n", (long)i); PackFile_Constant_dump(self->constants[i]); } @@ -80,23 +80,23 @@ PackFile_Constant_dump(struct PackFile_Constant *self) switch (self->type) { case PFC_NONE: /* TODO: OK to be silent here? */ - printf(" [ 'PFC_NONE', undef ],\n"); + PIO_printf(NULL," [ 'PFC_NONE', undef ],\n"); break; case PFC_NUMBER: - printf(" [ 'PFC_NUMBER', %g ],\n", self->number); + PIO_printf(NULL, " [ 'PFC_NUMBER', %g ],\n", self->number); break; case PFC_STRING: - printf(" [ 'PFC_STRING', {\n"); - printf(" FLAGS => 0x%04lx,\n", (long)self->string->flags); - printf(" ENCODING => %s,\n", self->string->encoding->name); - printf(" TYPE => %s,\n", self->string->type->name); - printf(" SIZE => %ld,\n", (long)self->string->bufused); + PIO_printf(NULL, " [ 'PFC_STRING', {\n"); + PIO_printf(NULL, " FLAGS => 0x%04lx,\n", (long)self->string->flags); + PIO_printf(NULL, " ENCODING => %s,\n", self->string->encoding->name); + PIO_printf(NULL, " TYPE => %s,\n", self->string->type->name); + PIO_printf(NULL, " SIZE => %ld,\n", (long)self->string->bufused); /* TODO: Won't do anything reasonable for most encodings */ - printf(" DATA => '%.*s'\n", + PIO_printf(NULL, " DATA => '%.*s'\n", (int)self->string->bufused, (char *)self->string->strstart); - printf(" } ],\n"); + PIO_printf(NULL, " } ],\n"); break; default: diff --git a/src/packfile.c b/src/packfile.c index 81687bea95..164149067d 100644 --- a/src/packfile.c +++ b/src/packfile.c @@ -48,14 +48,14 @@ PackFile_new(void) struct PackFile *pf = mem_sys_allocate(sizeof(struct PackFile)); if (!pf) { - fprintf(stderr, "PackFile_new: Unable to allocate!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate!\n"); return NULL; } pf->header = mem_sys_allocate(sizeof(struct PackFile_Header)); if(!pf->header) { - fprintf(stderr, "PackFile_new: Unable to allocate header!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate header!\n"); PackFile_destroy(pf); return NULL; } @@ -65,7 +65,7 @@ PackFile_new(void) mem_sys_allocate(sizeof(struct PackFile_FixupTable)); if (!pf->fixup_table) { - fprintf(stderr, "PackFile_new: Unable to allocate fixup table!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate fixup table!\n"); PackFile_destroy(pf); return NULL; } @@ -76,7 +76,7 @@ PackFile_new(void) mem_sys_allocate(sizeof(struct PackFile_ConstTable)); if (!pf->const_table) { - fprintf(stderr, "PackFile_new: Unable to allocate constant table!\n"); + PIO_eprintf(NULL, "PackFile_new: Unable to allocate constant table!\n"); PackFile_destroy(pf); return NULL; } @@ -106,7 +106,7 @@ PackFile_fetch_op(struct PackFile *pf, opcode_t *stream) { if(pf->fetch_op == NULL) return *stream; #if TRACE_PACKFILE == 2 - fprintf(stderr, "PackFile_fetch_op: Reordering.\n"); + PIO_eprintf(NULL, "PackFile_fetch_op: Reordering.\n"); #endif return (pf->fetch_op)(*stream); } @@ -148,14 +148,14 @@ PackFile_fetch_nv(struct PackFile *pf, opcode_t *stream) { FLOATVAL f; if(pf->fetch_nv == NULL) { #if TRACE_PACKFILE - fprintf(stderr, "PackFile_fetch_nv: Native [%d bytes]..\n", + PIO_eprintf(NULL, "PackFile_fetch_nv: Native [%d bytes]..\n", sizeof(FLOATVAL)); #endif memcpy(&f, stream, sizeof(FLOATVAL)); return f; } #if TRACE_PACKFILE - fprintf(stderr, "PackFile_fetch_nv: Byteordering..\n"); + PIO_eprintf(NULL, "PackFile_fetch_nv: Byteordering..\n"); #endif /* Here is where the size transforms get messy */ (pf->fetch_nv)((unsigned char *)&f, (unsigned char *)stream); @@ -184,7 +184,7 @@ void PackFile_assign_transforms(struct PackFile *pf) { } # if TRACE_PACKFILE else { - fprintf(stderr, "header->byteorder [%d] native byteorder [%d]\n", + PIO_eprintf(NULL, "header->byteorder [%d] native byteorder [%d]\n", pf->header->byteorder, PARROT_BIGENDIAN); } # endif @@ -205,7 +205,7 @@ void PackFile_destroy(struct PackFile *pf) { if (!pf) { - fprintf(stderr, "PackFile_destroy: pf == NULL!\n"); + PIO_eprintf(NULL, "PackFile_destroy: pf == NULL!\n"); return; } @@ -235,12 +235,12 @@ static INTVAL PackFile_check_segment_size(opcode_t segment_size, const char *debug) { #if TRACE_PACKFILE - printf("PackFile_unpack(): Unpacking %ld bytes for %s table...\n", + PIO_eprintf(NULL, "PackFile_unpack(): Unpacking %ld bytes for %s table...\n", segment_size, debug); #endif if (segment_size % sizeof(opcode_t)) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Illegal %s table segment size %ld (must be multiple of %ld)!\n", debug, segment_size, (long)sizeof(opcode_t)); return 0; @@ -291,7 +291,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, int i; if (!self) { - fprintf(stderr, "PackFile_unpack: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_unpack: self == NULL!\n"); return 0; } @@ -304,7 +304,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, if(header->wordsize != sizeof(opcode_t)) { self->need_wordsize = 1; if(header->wordsize == 0) { - fprintf(stderr, "PackFile_unpack: Invalid wordsize %d\n", + PIO_eprintf(NULL, "PackFile_unpack: Invalid wordsize %d\n", header->wordsize); return 0; } @@ -313,17 +313,17 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, PackFile_assign_transforms(self); #if TRACE_PACKFILE - fprintf(stderr, "wordsize: %d\n", header->wordsize); - fprintf(stderr, "byteorder: %d\n", header->byteorder); + PIO_eprintf(NULL, "wordsize: %d\n", header->wordsize); + PIO_eprintf(NULL, "byteorder: %d\n", header->byteorder); #endif /* * FIXME */ if(self->need_wordsize) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Unimplemented wordsize transform.\n"); - fprintf(stderr, "File has wordsize: %d (native is %d)\n", + PIO_eprintf(NULL, "File has wordsize: %d (native is %d)\n", header->wordsize, sizeof(opcode_t)); return 0; } @@ -337,9 +337,9 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, * The magic and opcodetype fields are in native byteorder. */ if (header->magic != PARROT_MAGIC) { - fprintf(stderr, "PackFile_unpack: Not a Parrot PackFile!\n"); + PIO_eprintf(NULL, "PackFile_unpack: Not a Parrot PackFile!\n"); #if TRACE_PACKFILE - fprintf(stderr, "Magic number was [%x] not [%x]\n", + PIO_eprintf(NULL, "Magic number was [%x] not [%x]\n", header->magic, PARROT_MAGIC); #endif return 0; @@ -348,7 +348,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, header->opcodetype = PackFile_fetch_op(self, cursor++); #if TRACE_PACKFILE - fprintf(stderr, "PackFile_unpack(): Magic verified.\n"); + PIO_eprintf(NULL, "PackFile_unpack(): Magic verified.\n"); #endif /* @@ -363,7 +363,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, if (!PackFile_FixupTable_unpack(self->fixup_table, cursor, header->fixup_ss)) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Error reading fixup table segment!\n"); return 0; } @@ -383,7 +383,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, if (!PackFile_ConstTable_unpack(interpreter, self, self->const_table, cursor, header->const_ss)) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Error reading constant table segment!\n"); return 0; } @@ -407,7 +407,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, self->byte_code = mem_sys_allocate(self->byte_code_size); if (!self->byte_code) { - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_unpack: Unable to allocate memory to copy byte code!\n"); self->byte_code_size = 0; return 0; @@ -422,7 +422,7 @@ PackFile_unpack(struct Parrot_Interp *interpreter, struct PackFile *self, for(i = 0; i < (int)(self->byte_code_size / sizeof(opcode_t)); i++) { self->byte_code[i] = PackFile_fetch_op(self, cursor++); #if TRACE_PACKFILE - fprintf(stderr, "op[%u]->[%u]\n", *(cursor-1), + PIO_eprintf(NULL, "op[%u]->[%u]\n", *(cursor-1), self->byte_code[i]); #endif } @@ -453,7 +453,7 @@ void PackFile_FixupTable_clear(struct PackFile_FixupTable *self) { if (!self) { - fprintf(stderr, "PackFile_FixupTable_clear: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_FixupTable_clear: self == NULL!\n"); return; } @@ -507,7 +507,7 @@ PackFile_ConstTable_clear(struct PackFile_ConstTable *self) opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_clear: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_clear: self == NULL!\n"); return; } @@ -551,7 +551,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_unpack: self == NULL!\n"); + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack: self == NULL!\n"); return 0; } @@ -562,7 +562,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, self->const_count = PackFile_fetch_op(pf, cursor++); #if TRACE_PACKFILE - printf("PackFile_ConstTable_unpack(): Unpacking %ld constants...\n", + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack(): Unpacking %ld constants...\n", self->const_count); #endif @@ -575,7 +575,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, sizeof(struct PackFile_Constant *)); if (!self->constants) { - fprintf(stderr, + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack: Could not allocate memory for array!\n"); self->const_count = 0; return 0; @@ -584,7 +584,7 @@ PackFile_ConstTable_unpack(struct Parrot_Interp *interpreter, for (i = 0; i < self->const_count; i++) { INTVAL rc; #if TRACE_PACKFILE - printf("PackFile_ConstTable_unpack(): Unpacking constant %ld...\n", i); + PIO_eprintf(interpreter, "PackFile_ConstTable_unpack(): Unpacking constant %ld...\n", i); #endif self->constants[i] = PackFile_Constant_new(); @@ -644,7 +644,7 @@ void PackFile_Constant_destroy(struct PackFile_Constant *self) { if (!self) { - fprintf(stderr, "PackFile_Constant_destroy: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_Constant_destroy: self == NULL!\n"); return; } @@ -668,7 +668,7 @@ PackFile_Constant_destroy(struct PackFile_Constant *self) break; default: - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_Constant_clear: Unrecognized type '%c' (%ld)!\n", (char)self->type, self->type); return; @@ -784,9 +784,9 @@ PackFile_Constant_unpack(struct Parrot_Interp *interpreter, size = PackFile_fetch_op(pf, cursor++); #if TRACE_PACKFILE - printf("PackFile_Constant_unpack(): Type is %ld ('%c')...\n", type, + PIO_eprintf(NULL, "PackFile_Constant_unpack(): Type is %ld ('%c')...\n", type, (char)type); - printf("PackFile_Constant_unpack(): Size is %ld...\n", size); + PIO_eprintf(NULL, "PackFile_Constant_unpack(): Size is %ld...\n", size); #endif switch (type) { @@ -807,7 +807,7 @@ PackFile_Constant_unpack(struct Parrot_Interp *interpreter, break; default: - fprintf(stderr, + PIO_eprintf(NULL, "PackFile_Constant_clear: Unrecognized type '%c' during unpack!\n", (char)type); return 0; @@ -860,7 +860,7 @@ PackFile_Constant_unpack_number(struct PackFile * pf, * determined by Configure. */ #if TRACE_PACKFILE - fprintf(stderr, + PIO_eprintf(NULL, "FIXME: PackFile_Constant_unpack_number: assuming size of FLOATVAL!\n"); #endif self->number = PackFile_fetch_nv(pf, (opcode_t *)cursor); @@ -921,11 +921,11 @@ PackFile_Constant_unpack_string(struct Parrot_Interp *interpreter, size = (size_t)PackFile_fetch_op(pf, cursor++); #if TRACE_PACKFILE - printf("PackFile_Constant_unpack_string(): flags are 0x%04x...\n", flags); - printf("PackFile_Constant_unpack_string(): encoding is %ld...\n", + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): flags are 0x%04x...\n", flags); + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): encoding is %ld...\n", encoding); - printf("PackFile_Constant_unpack_string(): type is %ld...\n", type); - printf("PackFile_Constant_unpack_string(): size is %ld...\n", size); + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): type is %ld...\n", type); + PIO_eprintf(NULL, "PackFile_Constant_unpack_string(): size is %ld...\n", size); #endif self->type = PFC_STRING; diff --git a/src/packout.c b/src/packout.c index 8c819efb2b..96fadba467 100644 --- a/src/packout.c +++ b/src/packout.c @@ -37,23 +37,23 @@ PackFile_pack_size(struct PackFile *self) segment_length_size = sizeof(opcode_t); #if TRACE_PACKFILE - printf("getting fixup table size...\n"); + PIO_eprintf(NULL, "getting fixup table size...\n"); #endif fixup_table_size = PackFile_FixupTable_pack_size(self->fixup_table); #if TRACE_PACKFILE - printf(" ... it is %ld\n", fixup_table_size); + PIO_eprintf(NULL, " ... it is %ld\n", fixup_table_size); #endif #if TRACE_PACKFILE - printf("getting const table size...\n"); + PIO_eprintf(NULL, "getting const table size...\n"); #endif const_table_size = PackFile_ConstTable_pack_size(self->const_table); #if TRACE_PACKFILE - printf(" ... it is %ld\n", const_table_size); + PIO_eprintf(NULL, " ... it is %ld\n", const_table_size); #endif return header_size + magic_size + oct_size @@ -161,7 +161,7 @@ PackFile_ConstTable_pack_size(struct PackFile_ConstTable *self) opcode_t size = 0; if (!self) { - fprintf(stderr, "PackFile_ConstTable_size: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_size: self == NULL!\n"); return -1; } @@ -188,7 +188,7 @@ PackFile_ConstTable_pack(struct PackFile *packfile, opcode_t i; if (!self) { - fprintf(stderr, "PackFile_ConstTable_pack: self == NULL!\n"); + PIO_eprintf(NULL, "PackFile_ConstTable_pack: self == NULL!\n"); return; } @@ -222,7 +222,7 @@ static int find_in_const(PMC *key, int type) else if (type == PFC_NUMBER && ct->constants[i]->number == key->cache.num_val) return i; - fprintf(stderr, "find_in_const: couldn't find const for key\n"); + PIO_eprintf(NULL, "find_in_const: couldn't find const for key\n"); exit(1); } /*************************************** @@ -360,7 +360,7 @@ PackFile_Constant_pack(struct PackFile_Constant *self, opcode_t *packed) *cursor++ = key->cache.int_val; break; default: - fprintf(stderr, "PackFile_Constant_pack: " + PIO_eprintf(NULL, "PackFile_Constant_pack: " "unsupported constant type\n"); exit(1); } @@ -371,7 +371,7 @@ PackFile_Constant_pack(struct PackFile_Constant *self, opcode_t *packed) default: /* TODO: OK to be silent here? */ /* ARGH, don't be silent -lt */ - fprintf(stderr, "PackFile_Constant_pack: unsupported constant\n"); + PIO_eprintf(NULL, "PackFile_Constant_pack: unsupported constant\n"); exit(1); break; } diff --git a/src/runops_cores.c b/src/runops_cores.c index b8e48c5eda..5f52f354f7 100644 --- a/src/runops_cores.c +++ b/src/runops_cores.c @@ -52,7 +52,7 @@ runops_cgoto_core(struct Parrot_Interp *interpreter, opcode_t *pc) pc = cg_core(pc, interpreter); return pc; #else - fprintf(stderr, "Computed goto unavailable in this configuration.\n"); + PIO_eprintf(interpreter, "Computed goto unavailable in this configuration.\n"); exit(1); #endif } diff --git a/src/spf_render.c b/src/spf_render.c new file mode 100644 index 0000000000..b47f871764 --- /dev/null +++ b/src/spf_render.c @@ -0,0 +1,646 @@ +/* spf_render.c + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id$ + * Overview: + * Implements the main function that drives the Parrot_sprintf + * family and its utility functions. + * Data Structure and Algorithms: + * History: + * Notes: + * References: misc.h, misc.c, spf_vtable.c + */ + +#define IN_SPF_SYSTEM + +#include "parrot/parrot.h" + +/* Per Dan's orders, we will not use sprintf if snprintf isn't + * around for us. + */ +#ifdef _WIN32 +# define snprintf _snprintf +#endif + +/* UTILITY FUNCTIONS */ + +static void +uint_to_str(struct Parrot_Interp *interpreter, STRING *out, + char *tc, UHUGEINTVAL num, char base) +{ + int i = 0, cur2; + char cur; + + do { + cur = (char)(num % base); + + if (cur < 10) { + tc[i] = (char)('0' + cur); + } + else { + tc[i] = (char)('a' + cur - 10); + } + + i++; + } while (num /= base); + + cur2 = i - 1; + + /* This fixes the problems some people have experienced + * with precision--the string was being reused without + * being cleared first. + */ + if(string_compare(interpreter, out, cstr2pstr("-")) != 0) { + string_set(interpreter, out, cstr2pstr("")); + } + + for (i = 0; i <= cur2; i++) { + string_append(interpreter, out, char2pstr(tc[cur2 - i]), 0); + } +} + +static void +int_to_str(struct Parrot_Interp *interpreter, STRING *out, + char *tc, HUGEINTVAL num, char base) +{ + string_set(interpreter, out, cstr2pstr("")); + + if (num < 0) { + string_append(interpreter, out, cstr2pstr("-"), 0); + num = -num; + } + uint_to_str(interpreter, out, tc, (UHUGEINTVAL) num, base); +} + +/* handle +, -, 0, #, space, width, and prec. */ +static void +handle_flags(struct Parrot_Interp *interpreter, + SpfInfo info, STRING *str, INTVAL is_int_type, const char *prefix) +{ + UINTVAL i; + UINTVAL len = string_length(str); + + if (is_int_type) { + /* +, space */ + if (string_ord(str, 0) != '-') { + if (info->flags & FLAG_PLUS) { + string_set(interpreter, str, + string_concat(interpreter, cstr2pstr("+"), str, 0)); + len++; + } + else if (info->flags & FLAG_SPACE) { + string_set(interpreter, str, + string_concat(interpreter, cstr2pstr(" "), str, 0)); + len++; + } + } + + /* # */ + if (info->flags & FLAG_SHARP && prefix && prefix[0]) { + string_set(interpreter, str, + string_concat(interpreter, cstr2pstr(prefix), str, 0)); + len += strlen(prefix); + } + + /* precision */ + if (info->flags & FLAG_PREC) { + info->flags |= FLAG_WIDTH; + if (string_ord(str, 0) == '-' || string_ord(str, 0) == '+') { + info->width = info->prec + 1; + } + else { + info->width = info->prec; + } + } + } + else { + /* string precision */ + if (info->flags & FLAG_PREC && info->prec < len) { + string_chopn(str, -(info->prec)); + len = info->prec; + } + } + + if (info->flags & FLAG_WIDTH) { + STRING *fill; + + if (info->flags & FLAG_ZERO) { + fill = cstr2pstr("0"); + } + else { + fill = cstr2pstr(" "); + } + + string_repeat(interpreter, fill, info->width - (len - 1), &fill); + + if (info->flags & FLAG_MINUS) { /* left-align */ + string_append(interpreter, str, fill, 0); + } + else { /* right-align */ + string_set(interpreter, str, string_concat(interpreter, + fill, str, 0)); + } + } +} + + +/* Turn the info structure back into an sprintf format. Far from being + * pointless, this is used to call snprintf() when we're confronted with + * a float. + */ + +static void +gen_sprintf_call(struct Parrot_Interp *interpreter, STRING *ts, char *out, + SpfInfo info, char thingy) +{ + int i = 0; + char tc[PARROT_SPRINTF_BUFFER_SIZE]; + out[i++] = '%'; + + if (info->flags) { + if (info->flags & FLAG_MINUS) { + out[i++] = '-'; + } + if (info->flags & FLAG_PLUS) { + out[i++] = '+'; + } + if (info->flags & FLAG_ZERO) { + out[i++] = '0'; + } + if (info->flags & FLAG_SPACE) { + out[i++] = ' '; + } + if (info->flags & FLAG_SHARP) { + out[i++] = '#'; + } + } + + if (info->flags & FLAG_WIDTH) { + if (info->width > PARROT_SPRINTF_BUFFER_SIZE - 1) { + info->width = PARROT_SPRINTF_BUFFER_SIZE; + } + uint_to_str(interpreter, ts, tc, info->width, 10); + strcpy(out + i, string_to_cstring(interpreter, ts)); + i = strlen(out); + } + + if (info->flags & FLAG_PREC) { + if (info->prec > PARROT_SPRINTF_MAX_PREC) { + info->prec = PARROT_SPRINTF_MAX_PREC; + } + + out[i++] = '.'; + uint_to_str(interpreter, ts, tc, info->prec, 10); + strcpy(out + i, string_to_cstring(interpreter, ts)); + i = strlen(out); + } + + out[i++] = thingy; + out[i] = 0; +} + + +/* This is the engine that does all the formatting. */ + +STRING * +Parrot_sprintf_format(struct Parrot_Interp *interpreter, STRING *pat, + SPRINTF_OBJ * obj) +{ + INTVAL i; + STRING *targ = string_make(interpreter, NULL, 0, NULL, 0, NULL); + + /* ts is used almost universally as an intermediate target; + * tc is used as a temporary buffer by uint_to_string and + * as a target by gen_sprintf_call. + */ + STRING *ts; + char tc[PARROT_SPRINTF_BUFFER_SIZE]; + + + for (i = 0; i < (INTVAL) string_length(pat); i++) { + if (string_ord(pat, i) == '%') { /* % */ + if (string_ord(pat, i + 1) == '%') { + i++; + } + else { + /* hoo boy, here we go... */ + + /* Various data types we may need */ + void *ptr; + STRING *string; + PMC *pmc; + HUGEFLOATVAL thefloat; + HUGEINTVAL theint = 0; + UHUGEINTVAL theuint = 0; + + /* Storage for flags, etc. */ + struct spfinfo_t info = { 0, 0, 0, 0, 0 }; + + /* Reset temporaries */ + ts = string_make(interpreter, NULL, 0, NULL, 0, NULL); + tc[0] = '\0'; + +/* This can be really hard to understand, so I'll try to explain beforehand. + * A rough grammar for a printf format is: + * + * grammar Parrot::PrintF_Format { + * rule format { + * ( )* + * } + * + * rule other_stuff { + * <[^\%]> | \%\% + * } + * + * rule field { + * \% + * ? + * ? + * [\.]? + * ? + * + * } + * + * rule flags { + * <[ + * + # prefix with a + if necessary + * - # left-align + * 0 # zero-pad + * # space-pad + * \# # 0, 0x on octal, hex; force decimal point on float + * ]>+ + * } + * + * rule width { + * [\d|\*]+ # minimum width + * } + * + * rule prec { + * [\d|\*]+ # width on integers; + * # number of digits after decimal on floats; + * # maximum width on strings + * } + * + * rule size { + * <[ + * h # short (or float) + * l # long + * H # HUGEwhateverVAL (long [long]?, [long]? double) + * v # whateverVAL + * O # opcode_t + * P # really a PMC + * S # Parrot string (only with %s) + * ]> + * } + * + * rule term { + * <[ + * c # char + * d # integer + * i # integer + * o # octal + * x # hex + * X # hex with capital X (if #) + * b # binary + * B # binary with capital B (if #) + * u # unsigned integer + * p # pointer + * + * e # 1e1 + * E # 1E1 + * f # 1.0 + * g # 1, 0.1, 1e1 + * G # 1, 0.1, 1E1 + * + * s # string + * ]> + * } + * } + * + * Complication: once upon a time, %P existed. Now you should + * use %Ps, %Pd or %Pf, but we still need to support the old form. + * The same is true of %S--%Ss is the best form, but %S is still + * supported. + * + * The implementation of Parrot_vsprintf is surprisingly similar to this + * regex, even though the two were developed semi-independently. + * Parrot_vsprintf keeps track of what it expects to see next (the + * 'phase')--flags, width, precision, size, or field type (term). If it + * doesn't find a character that fits whatever it's expecting, it sets + * info.phase to the next thing and tries it. The first four phases just + * set flags--the last does all the work. + */ + + for (i++; i < (INTVAL) string_length(pat) + && info.phase != PHASE_DONE; i++) { + INTVAL ch = string_ord(pat, i); + + switch (info.phase) { + /*@fallthrough@ */ case PHASE_FLAGS: + switch (ch) { + case '-': + info.flags |= FLAG_MINUS; + break; + + case '+': + info.flags |= FLAG_PLUS; + break; + + case '0': + info.flags |= FLAG_ZERO; + break; + + case ' ': + info.flags |= FLAG_SPACE; + break; + + case '#': + info.flags |= FLAG_SHARP; + break; + + default: + info.phase = PHASE_WIDTH; + } + + + /*@fallthrough@ */ case PHASE_WIDTH: + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '8': + case '9': + info.flags |= FLAG_WIDTH; + info.width *= 10; + info.width += ch - '0'; + continue; + + case '*': + info.flags |= FLAG_WIDTH; + info.width *= 10; + info.width += obj->getint(interpreter, + SIZE_XVAL, obj); + continue; + + case '.': + info.phase = PHASE_PREC; + continue; + + default: + info.phase = PHASE_PREC; + } + + + /*@fallthrough@ */ case PHASE_PREC: + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '8': + case '9': + info.flags |= FLAG_PREC; + info.prec *= 10; + info.prec += ch - '0'; + continue; + + case '*': + info.flags |= FLAG_PREC; + info.prec *= 10; + info.prec += obj->getint(interpreter, + SIZE_XVAL, obj); + continue; + + default: + info.phase = PHASE_TYPE; + } + + /*@fallthrough@ */ case PHASE_TYPE: + switch (ch) { + case 'h': + info.type = SIZE_SHORT; + continue; + + case 'l': + info.type = SIZE_LONG; + continue; + + case 'H': + info.type = SIZE_HUGE; + continue; + + case 'v': + info.type = SIZE_XVAL; + continue; + + case 'O': + info.type = SIZE_OPCODE; + continue; + + case 'P': + info.type = SIZE_PMC; + continue; + + case 'S': + info.type = SIZE_PSTR; + continue; + + default: + info.phase = PHASE_TERM; + } + + + /*@fallthrough@ */ case PHASE_TERM: + switch (ch) { + /* INTEGERS */ + case 'c': + string_append(interpreter, targ, + obj->getchr(interpreter, + info.type, obj), 0); + break; + + case 'd': + case 'i': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 10); + + handle_flags(interpreter, &info, ts, 1, NULL); + + string_append(interpreter, targ, ts, 0); + break; + + case 'o': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 8); + + handle_flags(interpreter, &info, ts, 1, "0"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'x': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 16); + + handle_flags(interpreter, &info, ts, 1, "0x"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'X': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 16); + + handle_flags(interpreter, &info, ts, 1, "0X"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'b': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 2); + + handle_flags(interpreter, &info, ts, 1, "0b"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'B': + theint = obj->getint(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, theint, 2); + + handle_flags(interpreter, &info, ts, 1, "0B"); + + string_append(interpreter, targ, ts, 0); + break; + + case 'u': + theuint = + obj->getuint(interpreter, info.type, obj); + uint_to_str(interpreter, ts, tc, theuint, 10); + + handle_flags(interpreter, &info, ts, 1, NULL); + + string_append(interpreter, targ, ts, 0); + break; + + case 'p': + ptr = obj->getptr(interpreter, info.type, obj); + int_to_str(interpreter, ts, tc, + (HUGEINTVAL) (size_t) ptr, 16); + + handle_flags(interpreter, &info, ts, 1, "0x"); + + string_append(interpreter, targ, ts, 0); + break; + + /* FLOATS - We cheat on these and use snprintf. */ + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + thefloat = obj->getfloat + (interpreter, info.type, obj); + gen_sprintf_call(interpreter, ts, tc, &info, ch); + string_set(interpreter, ts, cstr2pstr(tc)); + /* XXX lost precision if %Hg or whatever */ + snprintf(tc, PARROT_SPRINTF_BUFFER_SIZE, + string_to_cstring(interpreter, ts), + (double)thefloat); + +#if _WIN32 + /* Microsoft uses a retarded, broken, nonstandard + * behavior with regards to signs, exponents and + * precision: it doesn't count the + as part of the + * precision. We'll fix it ourselves if need be. + * XXX this bug might also apply to %e and %E + */ + + if(tolower(ch) == 'g') { + UINTVAL i; + for(i=0; i < strlen(tc); i++) { + if(tolower(tc[i]) == 'e' && + (tc[i+1] == '+' || tc[i+1] == '-')) { + tc[i+2]='\0'; + strcat(tc, &(tc[i+3])); + } + } + } +#endif + + string_append(interpreter, targ, cstr2pstr(tc), 0); + break; + + /* STRINGS */ + case 's': + CASE_s: + string = obj->getstring + (interpreter, info.type, obj); + + string_set(interpreter, ts, string); + + handle_flags(interpreter, &info, ts, 0, NULL); + + string_append(interpreter, targ, ts, 0); + + break; + + default: + /* fake the old %P and %S commands */ + if (info.type == SIZE_PMC + || info.type == SIZE_PSTR) { + i--; + goto CASE_s; + /* case 's' will see the SIZE_PMC or SIZE_PSTR + * and assume it was %Ps (or %Ss). Genius, + * no? + */ + } + else { + internal_exception(INVALID_CHARACTER, + "'%c' is not a valid sprintf format", + ch); + } + } + + info.phase = PHASE_DONE; + break; + + case PHASE_DONE: + /* This is the terminating condition of the surrounding + * loop, so... + */ + PANIC("We can't be here"); + } + } + } + + i--; + } + else { + STRING *substr = NULL; + string_substr(interpreter, pat, i, 1, &substr); + string_append(interpreter, targ, substr, 0); + } + } + + return targ; +} + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: +*/ diff --git a/src/spf_vtable.c b/src/spf_vtable.c new file mode 100644 index 0000000000..17da23a1dd --- /dev/null +++ b/src/spf_vtable.c @@ -0,0 +1,305 @@ +/* spf_vtable.c + * Copyright: (When this is determined...it will go here) + * CVS Info + * $Id$ + * Overview: + * Implements the two families of functions Parrot_sprintf + * may use to retrieve arguments. + * Data Structure and Algorithms: + * History: + * When I was first working on this implementation of + * sprintf, I ran into a problem. I wanted to re-use the + * implementation for a Parrot bytecode-level sprintf, but + * that couldn't be done, since it used va_* directly. For + * a while I thought about generating two versions of the + * source with a Perl script, but that seemed like overkill. + * Eventually I came across this idea--pass in a specialized + * vtable with methods for extracting things from the arglist, + * whatever it happened to be. This is the result. + * Notes: + * In the future, it may be deemed desirable to similarly + * vtable-ize appending things to the string, allowing for + * faster PIO_printf &c, as well as a version that writes + * directly to a C string. However, at this point neither + * of those is needed. + * References: misc.h, misc.c, spf_render.c + */ + +#define IN_SPF_SYSTEM + +#include "parrot/parrot.h" + +#include + +/* VARARGS CORE */ + +static STRING * +getchr_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + char ch = va_arg(*arg, char); + return string_make(interpreter, &ch, 1, NULL, 0, NULL); +} + +static HUGEINTVAL +getint_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_REG: + return (HUGEINTVAL) (int)va_arg(*arg, int); + case SIZE_SHORT: + /* "'short int' is promoted to 'int' when passed through '...'" */ + return (HUGEINTVAL) (short)va_arg(*arg, int); + case SIZE_LONG: + return (HUGEINTVAL) (long)va_arg(*arg, long); + case SIZE_HUGE: + return (HUGEINTVAL) (HUGEINTVAL) + va_arg(*arg, HUGEINTVAL); + case SIZE_XVAL: + return (HUGEINTVAL) (INTVAL) va_arg(*arg, INTVAL); + case SIZE_OPCODE: + return (HUGEINTVAL) (opcode_t) va_arg(*arg, opcode_t); + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return (HUGEINTVAL) (INTVAL) + (pmc->vtable->get_integer(interpreter, pmc)); + } + default: + PANIC("Invalid int type!"); + return 0; + } +} + +static UHUGEINTVAL +getuint_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_REG: + return (UHUGEINTVAL) (unsigned int) + va_arg(*arg, unsigned int); + case SIZE_SHORT: + /* short int promoted HLAGHLAGHLAGH. See note above */ + return (UHUGEINTVAL) (unsigned short) + va_arg(*arg, unsigned int); + case SIZE_LONG: + return (UHUGEINTVAL) (unsigned long) + va_arg(*arg, unsigned long); + case SIZE_HUGE: + return (UHUGEINTVAL) (UHUGEINTVAL) + va_arg(*arg, UHUGEINTVAL); + case SIZE_XVAL: + return (UHUGEINTVAL) (UINTVAL) va_arg(*arg, UINTVAL); + case SIZE_OPCODE: + return (UHUGEINTVAL) (opcode_t) va_arg(*arg, opcode_t); + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return (UHUGEINTVAL) (UINTVAL) + (pmc->vtable->get_integer(interpreter, pmc)); + } + default: + PANIC("Invalid uint type!"); + return 0; + } +} + +static HUGEFLOATVAL +getfloat_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_SHORT: + return (HUGEFLOATVAL) (float)va_arg(*arg, float); + case SIZE_REG: + return (HUGEFLOATVAL) (double)va_arg(*arg, double); + case SIZE_HUGE: + return (HUGEFLOATVAL) (HUGEFLOATVAL) + va_arg(*arg, HUGEFLOATVAL); + case SIZE_XVAL: + return (HUGEFLOATVAL) (FLOATVAL) + va_arg(*arg, FLOATVAL); + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return (HUGEFLOATVAL) (pmc->vtable->get_number(interpreter, pmc)); + } + default: + internal_exception(INVALID_CHARACTER, + "Internal sprintf doesn't recognize size %d for a float", + size); + return (HUGEFLOATVAL) 0.0; + } +} + +static STRING * +getstring_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + switch (size) { + case SIZE_REG:{ + char *cstr = (char *)va_arg(*arg, char *); + return cstr2pstr(cstr); + } + + case SIZE_PSTR: + return string_copy(interpreter, (STRING *) + va_arg(*arg, STRING *)); + + case SIZE_PMC:{ + PMC *pmc = (PMC *) va_arg(*arg, PMC *); + return pmc->vtable->get_string(interpreter, pmc); + } + + default: + internal_exception(INVALID_CHARACTER, + "Internal sprintf doesn't recognize size %d for a string", + size); + return NULL; + } +} + +static void * +getptr_va(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + va_list *arg = (va_list *) (obj->data); + + return (void *)va_arg(*arg, void *); +} + +SPRINTF_OBJ va_core = { + NULL, 0, getchr_va, getint_va, getuint_va, + getfloat_va, getstring_va, getptr_va +}; + + +/* PMC CORE */ + +static STRING * +getchr_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + return string_substr(interpreter, + tmp->vtable->get_string(interpreter, tmp), 0, 1, + NULL); +} + +static HUGEINTVAL +getint_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + HUGEINTVAL ret; + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + ret = (HUGEINTVAL) (tmp->vtable->get_integer(interpreter, tmp)); + + switch (size) { + case SIZE_SHORT: + ret = (HUGEINTVAL) (short)ret; + break; + /*case SIZE_REG: + * ret=(HUGEINTVAL)(int)ret; */ + break; + case SIZE_LONG: + ret = (HUGEINTVAL) (long)ret; + default: + /* nothing */ ; + } + + return ret; +} + +static UHUGEINTVAL +getuint_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + UHUGEINTVAL ret; + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + ret = (UHUGEINTVAL) (tmp->vtable->get_integer(interpreter, tmp)); + + switch (size) { + case SIZE_SHORT: + ret = (UHUGEINTVAL) (unsigned short)ret; + break; + /* case SIZE_REG: + * ret=(UHUGEINTVAL)(unsigned int)ret; + * break; */ + case SIZE_LONG: + ret = (UHUGEINTVAL) (unsigned long)ret; + default: + /* nothing */ ; + } + + return ret; +} + +static HUGEFLOATVAL +getfloat_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + HUGEFLOATVAL ret; + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + ret = (HUGEFLOATVAL) (tmp->vtable->get_number(interpreter, tmp)); + + switch (size) { + case SIZE_SHORT: + ret = (HUGEFLOATVAL) (float)ret; + break; + /* case SIZE_REG: + * ret=(HUGEFLOATVAL)(double)ret; + * break; */ + default: + /* nothing */ ; + } + + return ret; +} + +static STRING * +getstring_pmc(struct Parrot_Interp *interpreter, + INTVAL size, SPRINTF_OBJ * obj) +{ + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + return (STRING *)(tmp->vtable->get_string(interpreter, tmp)); +} + +static void * +getptr_pmc(struct Parrot_Interp *interpreter, INTVAL size, SPRINTF_OBJ * obj) +{ + PMC *tmp = ((PMC *) obj->data)->vtable->get_pmc_keyed_int(interpreter, + ((PMC *) obj->data), + &(obj->index)); + obj->index++; + /* XXX correct? */ + return (void *)(tmp->vtable->get_integer(interpreter, tmp)); +} + +SPRINTF_OBJ pmc_core = { + NULL, 0, getchr_pmc, getint_pmc, getuint_pmc, + getfloat_pmc, getstring_pmc, getptr_pmc +}; + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: +*/ diff --git a/src/string.c b/src/string.c index fc2cc21c24..2c6fe6b777 100644 --- a/src/string.c +++ b/src/string.c @@ -81,6 +81,21 @@ make_COW_reference(struct Parrot_Interp *interpreter, STRING *s) return d; } +static void +make_COW_reference_from_header(struct Parrot_Interp *interpreter, STRING *s, STRING *d) { + if (s->flags & BUFFER_constant_FLAG) { + s->flags |= BUFFER_COW_FLAG|BUFFER_external_FLAG; + copy_string_header(d, s); + d->flags &= ~(UINTVAL)(BUFFER_constant_FLAG); + } + else {; + s->flags |= BUFFER_COW_FLAG; + copy_string_header(d, s); + } +} + + + /* Basic string stuff - creation, enlargement, destruction, etc. */ /*=for api string string_init @@ -788,6 +803,21 @@ string_bool(const STRING *s) return 1; /* it must be true */ } +/*=for api string string_set + * Set the contents of one string to the contents of another. + */ +STRING * +string_set(struct Parrot_Interp *interpreter, STRING *dest, STRING *src) { + if(dest) { + make_COW_reference_from_header(interpreter, src, dest); + } + else { + dest=make_COW_reference(interpreter, src); + } + + return dest; +} + /* A number is such that: sign = '+' | '-' digit = "Any code point considered a digit by the chartype" @@ -956,15 +986,10 @@ string_from_int(struct Parrot_Interp * interpreter, INTVAL i) { STRING * string_from_num(struct Parrot_Interp * interpreter, FLOATVAL f) { - char buff[200]; - STRING* s; -#ifdef HAS_SNPRINTF - snprintf(buff, sizeof(buff), FLOATVAL_FMT, f); -#else - sprintf(buff, FLOATVAL_FMT, f); /* XXX buffer overflow! */ -#endif - s = string_make(interpreter, buff, strlen(buff), NULL, 0, NULL); - return s; + /* Too damn hard--hand it off to Parrot_sprintf, which'll probably + use the system sprintf anyway, but has gigantic buffers that are + awfully hard to overflow. */ + return Parrot_sprintf_c(interpreter, "%vg", f); } const char * diff --git a/src/trace.c b/src/trace.c index b3b5e7c6ff..2a68c6ba23 100644 --- a/src/trace.c +++ b/src/trace.c @@ -17,55 +17,74 @@ *=for api interpreter trace_key_dump * Prints a key to stderr. */ + +void +dump_pmc(struct Parrot_Interp *interpreter, PMC* pmc) { + if(pmc) { + if(pmc->vtable) { + PIO_eprintf(interpreter, "%S=PMC(%#p Str:\"%PS\" Num:%Pg Int:%Pd)", + pmc->vtable->name(interpreter, pmc), pmc, pmc, pmc, pmc); + } + else { + PIO_eprintf(interpreter, "PMC(NULL)"); + } + } + else { + PIO_eprintf(interpreter, "NULL"); + } +} + void trace_key_dump(struct Parrot_Interp *interpreter, PMC *key) { char *escaped; STRING *s; - fprintf(stderr, "["); + PIO_eprintf(interpreter, "["); while (key) { switch (key->flags & KEY_type_FLAGS) { case 0: break; case KEY_integer_FLAG: - fprintf(stderr, INTVAL_FMT, key->cache.int_val); + PIO_eprintf(interpreter, "%vi", key->cache.int_val); break; case KEY_number_FLAG: - fprintf(stderr, FLOATVAL_FMT, key->cache.num_val); + PIO_eprintf(interpreter, "%vg", key->cache.num_val); break; case KEY_string_FLAG: s = key->cache.string_val; + /* XXX do it w/o degrading to C string */ escaped = PDB_escape(s->bufstart, s->strlen); - fprintf(stderr, "\"%s\"", escaped); + PIO_eprintf(interpreter, "\"%s\"", escaped); break; case KEY_integer_FLAG|KEY_register_FLAG: - fprintf(stderr, "I" INTVAL_FMT "=" INTVAL_FMT, key->cache.int_val, + PIO_eprintf(interpreter, "I%vd=%vd", key->cache.int_val, interpreter->ctx.int_reg.registers[key->cache.int_val]); break; case KEY_number_FLAG|KEY_register_FLAG: - fprintf(stderr, "I" INTVAL_FMT "=" FLOATVAL_FMT, key->cache.int_val, + PIO_eprintf(interpreter, "I%vd=%vd", key->cache.int_val, interpreter->ctx.num_reg.registers[key->cache.int_val]); break; case KEY_string_FLAG|KEY_register_FLAG: s = interpreter->ctx.string_reg.registers[key->cache.int_val]; escaped = PDB_escape(s->bufstart, s->strlen); - fprintf(stderr, "S" INTVAL_FMT "=\"%s\"", key->cache.int_val, escaped); + PIO_eprintf(interpreter, "S%vd=\"%s\"", key->cache.int_val, escaped); break; case KEY_pmc_FLAG|KEY_register_FLAG: - fprintf(stderr, "P" INTVAL_FMT, key->cache.int_val); + PIO_eprintf(interpreter, "P%vd=", key->cache.int_val); + dump_pmc(interpreter, interpreter->ctx.pmc_reg.registers[key->cache.int_val]); break; default: - fprintf(stderr, "??"); + PIO_eprintf(interpreter, "??"); } key = key->data; - if (key) fprintf(stderr, ";"); + if (key) PIO_eprintf(interpreter, ";"); } - fprintf(stderr, "]"); + PIO_eprintf(interpreter, "]"); } /* @@ -80,52 +99,52 @@ trace_op_dump(struct Parrot_Interp *interpreter, opcode_t *code_start, INTVAL i; char *escaped; - fprintf(stderr, "PC=%ld; OP=%ld (%s)", (long)(pc - code_start), *pc, + PIO_eprintf(interpreter, "PC=%vu; OP=%Ou (%s)", (UINTVAL)(pc - code_start), *pc, interpreter->op_info_table[*pc].full_name); if (interpreter->op_info_table[*pc].arg_count > 1) { - fprintf(stderr, "; ARGS=("); + PIO_eprintf(interpreter, "; ARGS=("); for (i = 1; i < interpreter->op_info_table[*pc].arg_count; i++) { if (i > 1) { - fprintf(stderr, ", "); + PIO_eprintf(interpreter, ", "); } switch (interpreter->op_info_table[*pc].types[i]) { case PARROT_ARG_IC: - fprintf(stderr, INTVAL_FMT, *(pc + i)); + PIO_eprintf(interpreter, "%vd", *(pc + i)); break; case PARROT_ARG_NC: - fprintf(stderr, FLOATVAL_FMT, interpreter->code->const_table-> + PIO_eprintf(interpreter, "%vg", interpreter->code->const_table-> constants[*(pc + i)]->number); break; case PARROT_ARG_PC: /* what is a PMC constant look like? */ - fprintf(stderr, INTVAL_FMT, *(pc + i)); + PIO_eprintf(interpreter, "PMCc:%vd", *(pc + i)); break; case PARROT_ARG_SC: escaped = PDB_escape(interpreter->code->const_table-> constants[*(pc + i)]->string->strstart, interpreter->code->const_table-> constants[*(pc + i)]->string->strlen); - fprintf(stderr, "\"%s\"", escaped); + PIO_eprintf(interpreter, "\"%s\"", escaped); break; case PARROT_ARG_KC: trace_key_dump(interpreter, interpreter->code->const_table->constants[*(pc + i)]->key); break; case PARROT_ARG_KIC: - fprintf(stderr, "[" INTVAL_FMT "]", *(pc + i)); + PIO_eprintf(interpreter, "[%vd]", *(pc + i)); break; case PARROT_ARG_I: - fprintf(stderr, "I" INTVAL_FMT "=" INTVAL_FMT, *(pc + i), + PIO_eprintf(interpreter, "I%vd=%vd", *(pc + i), interpreter->ctx.int_reg.registers[*(pc + i)]); break; case PARROT_ARG_N: - fprintf(stderr, "N" INTVAL_FMT "=" FLOATVAL_FMT, *(pc + i), + PIO_eprintf(interpreter, "N%vd=%vg", *(pc + i), interpreter->ctx.num_reg.registers[*(pc + i)]); break; case PARROT_ARG_P: /* what does a PMC register look like? */ - fprintf(stderr, "P" INTVAL_FMT "=%p", *(pc + i), - interpreter->ctx.pmc_reg.registers[*(pc + i)]); + PIO_eprintf(interpreter, "P%vd=", *(pc + i)); + dump_pmc(interpreter, interpreter->ctx.pmc_reg.registers[*(pc + i)]); break; case PARROT_ARG_S: if (interpreter->ctx.string_reg.registers[*(pc + i)]) { @@ -133,19 +152,19 @@ trace_op_dump(struct Parrot_Interp *interpreter, opcode_t *code_start, registers[*(pc + i)]->strstart, interpreter->ctx.string_reg. registers[*(pc + i)]->strlen); - fprintf(stderr, "S" INTVAL_FMT "=\"%s\"", *(pc + i), + PIO_eprintf(interpreter, "S%vd=\"%s\"", *(pc + i), escaped); } else { - fprintf(stderr, "S" INTVAL_FMT "=(null)", *(pc + i)); + PIO_eprintf(interpreter, "S%vd=(null)", *(pc + i)); } break; case PARROT_ARG_K: - fprintf(stderr, "P" INTVAL_FMT "=", *(pc + i)); + PIO_eprintf(interpreter, "P%vd=", *(pc + i)); trace_key_dump(interpreter, interpreter->ctx.pmc_reg.registers[*(pc + i)]); break; case PARROT_ARG_KI: - fprintf(stderr, "[I" INTVAL_FMT "=" INTVAL_FMT "]", *(pc + i), + PIO_eprintf(interpreter, "I%vd=[%vd]", *(pc + i), interpreter->ctx.int_reg.registers[*(pc + i)]); break; case PARROT_ARG_OP: @@ -156,15 +175,15 @@ trace_op_dump(struct Parrot_Interp *interpreter, opcode_t *code_start, break; default: /* -Wall expects us to cover PARROT_ARG_OP somewhere. */ - fprintf(stderr, "?(%i)" INTVAL_FMT "=???", + PIO_eprintf(interpreter, "?(%i)%vd=???", interpreter->op_info_table[*pc].types[i], *(pc + i)); break; } } - fprintf(stderr, ")"); + PIO_eprintf(interpreter, ")"); } - fprintf(stderr, "\n"); + PIO_eprintf(interpreter, "\n"); } @@ -189,11 +208,11 @@ trace_op(struct Parrot_Interp *interpreter, opcode_t *code_start, trace_op_dump(interpreter, code_start, pc); } else if (pc) { - fprintf(stderr, "PC=%ld; OP=\n", (long)(pc - code_start)); + PIO_eprintf(interpreter, "PC=%ld; OP=\n", (long)(pc - code_start)); } /* Flush *stderr* now that we've output the trace info */ - (void)fflush(stderr); + PIO_flush(interpreter, PIO_STDERR(interpreter)); } diff --git a/src/warnings.c b/src/warnings.c index 6d6fac8ab1..fcd1dcdaab 100644 --- a/src/warnings.c +++ b/src/warnings.c @@ -18,27 +18,21 @@ Parrot_warn(struct Parrot_Interp *interpreter, INTVAL warnclass, return 2; } - targ = Parrot_vsprintf_c(interpreter, message, &args); - if (!targ) { - return -1; - } + targ = Parrot_vsprintf_c(interpreter, message, args); va_end(args); - targ = Parrot_sprintf_c( - interpreter, - "%S at %S line %d.\n", targ, - Default(interpreter, current_file, - string_make(interpreter, "?", 1, NULL, 0, NULL)), - Default(interpreter, current_line, 0) - ); - if (!targ) { return -1; } - if (PIO_write(interpreter, PIO_STDERR(interpreter), targ->strstart, - targ->bufused) < 0) { + if (PIO_eprintf(interpreter, "%S%S.\n", + targ, + interpreter ? Parrot_sprintf_c( + interpreter, " at %S line %d", interpreter->current_file, interpreter->current_line + ) : NULL + ) < 0) + { return -2; } else { @@ -60,25 +54,20 @@ Parrot_warn_s(struct Parrot_Interp *interpreter, INTVAL warnclass, return 2; } - targ = Parrot_vsprintf_s(interpreter, message, &args); - if (!targ) { - return -1; - } - + targ = Parrot_vsprintf_s(interpreter, message, args); va_end(args); - targ = Parrot_sprintf_c( - interpreter, "%S at %S line %d.\n", targ, - Default(interpreter, current_file, - string_make(interpreter, "?", 1, NULL, 0, NULL)), - Default(interpreter, current_line, 0) - ); if (!targ) { return -1; } - if (PIO_write(interpreter, PIO_STDERR(interpreter), targ->strstart, - targ->bufused) < 0) { + if (PIO_eprintf(interpreter, "%S%S.\n", + targ, + interpreter ? Parrot_sprintf_c( + interpreter, " at %S line %d", interpreter->current_file, interpreter->current_line + ) : NULL + ) < 0) + { return -2; } else { diff --git a/string.c b/string.c index fc2cc21c24..2c6fe6b777 100644 --- a/string.c +++ b/string.c @@ -81,6 +81,21 @@ make_COW_reference(struct Parrot_Interp *interpreter, STRING *s) return d; } +static void +make_COW_reference_from_header(struct Parrot_Interp *interpreter, STRING *s, STRING *d) { + if (s->flags & BUFFER_constant_FLAG) { + s->flags |= BUFFER_COW_FLAG|BUFFER_external_FLAG; + copy_string_header(d, s); + d->flags &= ~(UINTVAL)(BUFFER_constant_FLAG); + } + else {; + s->flags |= BUFFER_COW_FLAG; + copy_string_header(d, s); + } +} + + + /* Basic string stuff - creation, enlargement, destruction, etc. */ /*=for api string string_init @@ -788,6 +803,21 @@ string_bool(const STRING *s) return 1; /* it must be true */ } +/*=for api string string_set + * Set the contents of one string to the contents of another. + */ +STRING * +string_set(struct Parrot_Interp *interpreter, STRING *dest, STRING *src) { + if(dest) { + make_COW_reference_from_header(interpreter, src, dest); + } + else { + dest=make_COW_reference(interpreter, src); + } + + return dest; +} + /* A number is such that: sign = '+' | '-' digit = "Any code point considered a digit by the chartype" @@ -956,15 +986,10 @@ string_from_int(struct Parrot_Interp * interpreter, INTVAL i) { STRING * string_from_num(struct Parrot_Interp * interpreter, FLOATVAL f) { - char buff[200]; - STRING* s; -#ifdef HAS_SNPRINTF - snprintf(buff, sizeof(buff), FLOATVAL_FMT, f); -#else - sprintf(buff, FLOATVAL_FMT, f); /* XXX buffer overflow! */ -#endif - s = string_make(interpreter, buff, strlen(buff), NULL, 0, NULL); - return s; + /* Too damn hard--hand it off to Parrot_sprintf, which'll probably + use the system sprintf anyway, but has gigantic buffers that are + awfully hard to overflow. */ + return Parrot_sprintf_c(interpreter, "%vg", f); } const char * diff --git a/t/op/string.t b/t/op/string.t index ed48f6760b..09d6160b9d 100644 --- a/t/op/string.t +++ b/t/op/string.t @@ -1,6 +1,6 @@ #! perl -w -use Parrot::Test tests => 95; +use Parrot::Test tests => 96; use Test::More; output_is( <<'CODE', <strstart); - S = Parrot_sprintf_c(interpreter, "PerlHash[0x%x]\n", 256); - printf(S->strstart); - S = Parrot_sprintf_c(interpreter, "PerlHash[0x%lx]\n", 256); - printf(S->strstart); - S = Parrot_sprintf_c(interpreter, "Hello, %.2s!\n", "Parrot"); - printf(S->strstart); - } + int dummy_var; + STRING *S; + PMC *pmc; + INTVAL ival; + UINTVAL uval; + float fval; + double dval; + FLOATVAL fltval; + char *fmt; + struct Parrot_Interp * interpreter; + + interpreter = Parrot_new(); + Parrot_init(interpreter, (void*) &dummy_var); + + S = Parrot_sprintf_c(interpreter, "Hello, %s\n", "Parrot!"); + printf(string_to_cstring(interpreter, S)); + + S = Parrot_sprintf_c(interpreter, "PerlHash[0x%x]\n", 256); + printf(string_to_cstring(interpreter, S)); + + S = Parrot_sprintf_c(interpreter, "PerlHash[0x%lx]\n", 256); + printf(string_to_cstring(interpreter, S)); + + S = Parrot_sprintf_c(interpreter, "Hello, %.2s!\n", "Parrot"); + printf(string_to_cstring(interpreter, S)); + + S = Parrot_sprintf_c(interpreter, "Hello, %Ss", S); + printf(string_to_cstring(interpreter, S)); + + pmc=pmc_new(interpreter, enum_class_PerlInt); + pmc->vtable->set_integer_native(interpreter, pmc, 1); + S = Parrot_sprintf_c(interpreter, "== %Pd\n", pmc); + printf("%d %s", 1, string_to_cstring(interpreter, S)); + + ival = -255; + S = Parrot_sprintf_c(interpreter, "== %vd\n", ival); + printf("%d %s", (int) ival, string_to_cstring(interpreter, S)); + + uval = 256; + S = Parrot_sprintf_c(interpreter, "== %vu\n", uval); + printf("%u %s", (unsigned) uval, string_to_cstring(interpreter, S)); + + fval = 0.5; + S = Parrot_sprintf_c(interpreter, "== %f\n", fval); + printf("%f %s", fval, string_to_cstring(interpreter, S)); + + dval = 0.5; + S = Parrot_sprintf_c(interpreter, "== %5.3f\n", dval); + printf("%5.3f %s", dval, string_to_cstring(interpreter, S)); + + dval = 0.001; + S = Parrot_sprintf_c(interpreter, "== %g\n", dval); + printf("%g %s", dval, string_to_cstring(interpreter, S)); + + dval = 1.0e6; + S = Parrot_sprintf_c(interpreter, "== %g\n", dval); + printf("%g %s", dval, string_to_cstring(interpreter, S)); + + fltval = 0.5; + S = Parrot_sprintf_c(interpreter, "== %3.3g\n", fltval); + printf("%3.3g %s", (double) fltval, + string_to_cstring(interpreter, S)); + + /* Test we've not left junk behind on the stack */ + S = Parrot_sprintf_c(interpreter, "That's all, %s\n", "folks!"); + printf(string_to_cstring(interpreter, S)); + return 0; + } CODE Hello, Parrot! PerlHash[0x100] PerlHash[0x100] Hello, Pa! +Hello, Hello, Pa! +1 == 1 +-255 == -255 +256 == 256 +0.500000 == 0.500000 +0.500 == 0.500 +0.001 == 0.001 +1e+06 == 1e+06 +0.5 == 0.5 +That's all, folks! OUTPUT -} \ No newline at end of file +} diff --git a/trace.c b/trace.c index b3b5e7c6ff..2a68c6ba23 100644 --- a/trace.c +++ b/trace.c @@ -17,55 +17,74 @@ *=for api interpreter trace_key_dump * Prints a key to stderr. */ + +void +dump_pmc(struct Parrot_Interp *interpreter, PMC* pmc) { + if(pmc) { + if(pmc->vtable) { + PIO_eprintf(interpreter, "%S=PMC(%#p Str:\"%PS\" Num:%Pg Int:%Pd)", + pmc->vtable->name(interpreter, pmc), pmc, pmc, pmc, pmc); + } + else { + PIO_eprintf(interpreter, "PMC(NULL)"); + } + } + else { + PIO_eprintf(interpreter, "NULL"); + } +} + void trace_key_dump(struct Parrot_Interp *interpreter, PMC *key) { char *escaped; STRING *s; - fprintf(stderr, "["); + PIO_eprintf(interpreter, "["); while (key) { switch (key->flags & KEY_type_FLAGS) { case 0: break; case KEY_integer_FLAG: - fprintf(stderr, INTVAL_FMT, key->cache.int_val); + PIO_eprintf(interpreter, "%vi", key->cache.int_val); break; case KEY_number_FLAG: - fprintf(stderr, FLOATVAL_FMT, key->cache.num_val); + PIO_eprintf(interpreter, "%vg", key->cache.num_val); break; case KEY_string_FLAG: s = key->cache.string_val; + /* XXX do it w/o degrading to C string */ escaped = PDB_escape(s->bufstart, s->strlen); - fprintf(stderr, "\"%s\"", escaped); + PIO_eprintf(interpreter, "\"%s\"", escaped); break; case KEY_integer_FLAG|KEY_register_FLAG: - fprintf(stderr, "I" INTVAL_FMT "=" INTVAL_FMT, key->cache.int_val, + PIO_eprintf(interpreter, "I%vd=%vd", key->cache.int_val, interpreter->ctx.int_reg.registers[key->cache.int_val]); break; case KEY_number_FLAG|KEY_register_FLAG: - fprintf(stderr, "I" INTVAL_FMT "=" FLOATVAL_FMT, key->cache.int_val, + PIO_eprintf(interpreter, "I%vd=%vd", key->cache.int_val, interpreter->ctx.num_reg.registers[key->cache.int_val]); break; case KEY_string_FLAG|KEY_register_FLAG: s = interpreter->ctx.string_reg.registers[key->cache.int_val]; escaped = PDB_escape(s->bufstart, s->strlen); - fprintf(stderr, "S" INTVAL_FMT "=\"%s\"", key->cache.int_val, escaped); + PIO_eprintf(interpreter, "S%vd=\"%s\"", key->cache.int_val, escaped); break; case KEY_pmc_FLAG|KEY_register_FLAG: - fprintf(stderr, "P" INTVAL_FMT, key->cache.int_val); + PIO_eprintf(interpreter, "P%vd=", key->cache.int_val); + dump_pmc(interpreter, interpreter->ctx.pmc_reg.registers[key->cache.int_val]); break; default: - fprintf(stderr, "??"); + PIO_eprintf(interpreter, "??"); } key = key->data; - if (key) fprintf(stderr, ";"); + if (key) PIO_eprintf(interpreter, ";"); } - fprintf(stderr, "]"); + PIO_eprintf(interpreter, "]"); } /* @@ -80,52 +99,52 @@ trace_op_dump(struct Parrot_Interp *interpreter, opcode_t *code_start, INTVAL i; char *escaped; - fprintf(stderr, "PC=%ld; OP=%ld (%s)", (long)(pc - code_start), *pc, + PIO_eprintf(interpreter, "PC=%vu; OP=%Ou (%s)", (UINTVAL)(pc - code_start), *pc, interpreter->op_info_table[*pc].full_name); if (interpreter->op_info_table[*pc].arg_count > 1) { - fprintf(stderr, "; ARGS=("); + PIO_eprintf(interpreter, "; ARGS=("); for (i = 1; i < interpreter->op_info_table[*pc].arg_count; i++) { if (i > 1) { - fprintf(stderr, ", "); + PIO_eprintf(interpreter, ", "); } switch (interpreter->op_info_table[*pc].types[i]) { case PARROT_ARG_IC: - fprintf(stderr, INTVAL_FMT, *(pc + i)); + PIO_eprintf(interpreter, "%vd", *(pc + i)); break; case PARROT_ARG_NC: - fprintf(stderr, FLOATVAL_FMT, interpreter->code->const_table-> + PIO_eprintf(interpreter, "%vg", interpreter->code->const_table-> constants[*(pc + i)]->number); break; case PARROT_ARG_PC: /* what is a PMC constant look like? */ - fprintf(stderr, INTVAL_FMT, *(pc + i)); + PIO_eprintf(interpreter, "PMCc:%vd", *(pc + i)); break; case PARROT_ARG_SC: escaped = PDB_escape(interpreter->code->const_table-> constants[*(pc + i)]->string->strstart, interpreter->code->const_table-> constants[*(pc + i)]->string->strlen); - fprintf(stderr, "\"%s\"", escaped); + PIO_eprintf(interpreter, "\"%s\"", escaped); break; case PARROT_ARG_KC: trace_key_dump(interpreter, interpreter->code->const_table->constants[*(pc + i)]->key); break; case PARROT_ARG_KIC: - fprintf(stderr, "[" INTVAL_FMT "]", *(pc + i)); + PIO_eprintf(interpreter, "[%vd]", *(pc + i)); break; case PARROT_ARG_I: - fprintf(stderr, "I" INTVAL_FMT "=" INTVAL_FMT, *(pc + i), + PIO_eprintf(interpreter, "I%vd=%vd", *(pc + i), interpreter->ctx.int_reg.registers[*(pc + i)]); break; case PARROT_ARG_N: - fprintf(stderr, "N" INTVAL_FMT "=" FLOATVAL_FMT, *(pc + i), + PIO_eprintf(interpreter, "N%vd=%vg", *(pc + i), interpreter->ctx.num_reg.registers[*(pc + i)]); break; case PARROT_ARG_P: /* what does a PMC register look like? */ - fprintf(stderr, "P" INTVAL_FMT "=%p", *(pc + i), - interpreter->ctx.pmc_reg.registers[*(pc + i)]); + PIO_eprintf(interpreter, "P%vd=", *(pc + i)); + dump_pmc(interpreter, interpreter->ctx.pmc_reg.registers[*(pc + i)]); break; case PARROT_ARG_S: if (interpreter->ctx.string_reg.registers[*(pc + i)]) { @@ -133,19 +152,19 @@ trace_op_dump(struct Parrot_Interp *interpreter, opcode_t *code_start, registers[*(pc + i)]->strstart, interpreter->ctx.string_reg. registers[*(pc + i)]->strlen); - fprintf(stderr, "S" INTVAL_FMT "=\"%s\"", *(pc + i), + PIO_eprintf(interpreter, "S%vd=\"%s\"", *(pc + i), escaped); } else { - fprintf(stderr, "S" INTVAL_FMT "=(null)", *(pc + i)); + PIO_eprintf(interpreter, "S%vd=(null)", *(pc + i)); } break; case PARROT_ARG_K: - fprintf(stderr, "P" INTVAL_FMT "=", *(pc + i)); + PIO_eprintf(interpreter, "P%vd=", *(pc + i)); trace_key_dump(interpreter, interpreter->ctx.pmc_reg.registers[*(pc + i)]); break; case PARROT_ARG_KI: - fprintf(stderr, "[I" INTVAL_FMT "=" INTVAL_FMT "]", *(pc + i), + PIO_eprintf(interpreter, "I%vd=[%vd]", *(pc + i), interpreter->ctx.int_reg.registers[*(pc + i)]); break; case PARROT_ARG_OP: @@ -156,15 +175,15 @@ trace_op_dump(struct Parrot_Interp *interpreter, opcode_t *code_start, break; default: /* -Wall expects us to cover PARROT_ARG_OP somewhere. */ - fprintf(stderr, "?(%i)" INTVAL_FMT "=???", + PIO_eprintf(interpreter, "?(%i)%vd=???", interpreter->op_info_table[*pc].types[i], *(pc + i)); break; } } - fprintf(stderr, ")"); + PIO_eprintf(interpreter, ")"); } - fprintf(stderr, "\n"); + PIO_eprintf(interpreter, "\n"); } @@ -189,11 +208,11 @@ trace_op(struct Parrot_Interp *interpreter, opcode_t *code_start, trace_op_dump(interpreter, code_start, pc); } else if (pc) { - fprintf(stderr, "PC=%ld; OP=\n", (long)(pc - code_start)); + PIO_eprintf(interpreter, "PC=%ld; OP=\n", (long)(pc - code_start)); } /* Flush *stderr* now that we've output the trace info */ - (void)fflush(stderr); + PIO_flush(interpreter, PIO_STDERR(interpreter)); } diff --git a/warnings.c b/warnings.c index 6d6fac8ab1..fcd1dcdaab 100644 --- a/warnings.c +++ b/warnings.c @@ -18,27 +18,21 @@ Parrot_warn(struct Parrot_Interp *interpreter, INTVAL warnclass, return 2; } - targ = Parrot_vsprintf_c(interpreter, message, &args); - if (!targ) { - return -1; - } + targ = Parrot_vsprintf_c(interpreter, message, args); va_end(args); - targ = Parrot_sprintf_c( - interpreter, - "%S at %S line %d.\n", targ, - Default(interpreter, current_file, - string_make(interpreter, "?", 1, NULL, 0, NULL)), - Default(interpreter, current_line, 0) - ); - if (!targ) { return -1; } - if (PIO_write(interpreter, PIO_STDERR(interpreter), targ->strstart, - targ->bufused) < 0) { + if (PIO_eprintf(interpreter, "%S%S.\n", + targ, + interpreter ? Parrot_sprintf_c( + interpreter, " at %S line %d", interpreter->current_file, interpreter->current_line + ) : NULL + ) < 0) + { return -2; } else { @@ -60,25 +54,20 @@ Parrot_warn_s(struct Parrot_Interp *interpreter, INTVAL warnclass, return 2; } - targ = Parrot_vsprintf_s(interpreter, message, &args); - if (!targ) { - return -1; - } - + targ = Parrot_vsprintf_s(interpreter, message, args); va_end(args); - targ = Parrot_sprintf_c( - interpreter, "%S at %S line %d.\n", targ, - Default(interpreter, current_file, - string_make(interpreter, "?", 1, NULL, 0, NULL)), - Default(interpreter, current_line, 0) - ); if (!targ) { return -1; } - if (PIO_write(interpreter, PIO_STDERR(interpreter), targ->strstart, - targ->bufused) < 0) { + if (PIO_eprintf(interpreter, "%S%S.\n", + targ, + interpreter ? Parrot_sprintf_c( + interpreter, " at %S line %d", interpreter->current_file, interpreter->current_line + ) : NULL + ) < 0) + { return -2; } else {