| … | |
… | |
| 27 | use warnings; |
27 | use warnings; |
| 28 | use File::Path qw(rmtree); |
28 | use File::Path qw(rmtree); |
| 29 | use WeBWorK::PG::ImageGenerator; |
29 | use WeBWorK::PG::ImageGenerator; |
| 30 | use WeBWorK::PG::Translator; |
30 | use WeBWorK::PG::Translator; |
| 31 | use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry makeTempDirectory); |
31 | use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry makeTempDirectory); |
|
|
32 | BEGIN { |
| 32 | |
33 | |
|
|
34 | # This safe compartment is used to read the large macro files such as |
|
|
35 | # PG.pl, PGbasicmacros.pl and PGanswermacros and cache the results so that |
|
|
36 | # future calls have preloaded versions of these large files. |
|
|
37 | # This saves a significant amount of time. |
|
|
38 | |
|
|
39 | $WeBWorK::PG::Local::safeCache = new Safe; |
|
|
40 | # warn "Creating new Safe cache compartment ".$WeBWorK::PG::Local::safeCache->root; |
|
|
41 | } |
| 33 | sub new { |
42 | sub new { |
| 34 | my $invocant = shift; |
43 | my $invocant = shift; |
| 35 | my $class = ref($invocant) || $invocant; |
44 | my $class = ref($invocant) || $invocant; |
| 36 | my ( |
45 | my ( |
| 37 | $ce, |
46 | $ce, |
| … | |
… | |
| 55 | my $warnings = ""; |
64 | my $warnings = ""; |
| 56 | local $SIG{__WARN__} = sub { $warnings .= shift } |
65 | local $SIG{__WARN__} = sub { $warnings .= shift } |
| 57 | if $ce->{pg}->{options}->{catchWarnings}; |
66 | if $ce->{pg}->{options}->{catchWarnings}; |
| 58 | |
67 | |
| 59 | # create a Translator |
68 | # create a Translator |
| 60 | #warn "PG: creating a Translator\n"; |
69 | #warn "PG: creating a Translator\n"; |
| 61 | my $translator = WeBWorK::PG::Translator->new; |
70 | my $translator = WeBWorK::PG::Translator->new; |
| 62 | |
71 | |
| 63 | # set the directory hash |
72 | # set the directory hash |
| 64 | #warn "PG: setting the directory hash\n"; |
73 | #warn "PG: setting the directory hash\n"; |
| 65 | $translator->rh_directories({ |
74 | $translator->rh_directories({ |
| … | |
… | |
| 95 | $translator->environment($envir); |
104 | $translator->environment($envir); |
| 96 | |
105 | |
| 97 | # initialize the Translator |
106 | # initialize the Translator |
| 98 | #warn "PG: initializing the Translator\n"; |
107 | #warn "PG: initializing the Translator\n"; |
| 99 | $translator->initialize(); |
108 | $translator->initialize(); |
| 100 | |
109 | # $translator->dumpSafe; # debugging code |
|
|
110 | ############################################################################### |
|
|
111 | # Preload the macros files which are used routinely: PG.pl, dangerousMacros.pl, IO.pl |
|
|
112 | # PGbasicmacros.pl and PGanswermacros.pl |
|
|
113 | # Preloading the last two files safes a significant amount of time. |
|
|
114 | ############################################################################### |
|
|
115 | |
| 101 | # load IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load |
116 | # IO.pl, PG.pl, and dangerousMacros.pl are loaded using unrestricted_load |
|
|
117 | # This is hard wired into the Translator::pre_load_macro_files subroutine |
| 102 | # i'd like to change this at some point to have the same sort of interface to global.conf |
118 | # I'd like to change this at some point to have the same sort of interface to global.conf |
| 103 | # that the module loading does -- have a list of macros to load unrestrictedly. |
119 | # that the module loading does -- have a list of macros to load unrestrictedly. |
| 104 | #warn "PG: loading IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load\n"; |
120 | |
|
|
121 | # This has been replaced by the pre_load_macro_files subroutine. It loads AND caches the files. |
|
|
122 | # While PG.pl and dangerousMacros are not large, they are referred to by PGbasicmacros and PGanswermacros. |
|
|
123 | # Because these are loaded into the cached name space (e.g. Safe::Root1::) all calls to, say NEW_ANSWER_NAME |
|
|
124 | # are actually calls to Safe::Root1::NEW_ANSWER_NAME. It is useful to have these names inside the Safe::Root1: |
|
|
125 | # cached safe compartment. (NEW_ANSWER_NAME and all other subroutine names are also automatically exported into |
|
|
126 | # the current safe compartment Safe::Rootx:: |
|
|
127 | |
|
|
128 | # The headers of both PGbasicmacros and PGanswermacros has code that insures that the constants used are imported into |
|
|
129 | # the current safe compartment. This involves evaluating references to, say $main::displayMode, at runtime to insure that main |
|
|
130 | # refers to Safe::Rootx:: and NOT to Safe::Root1::, which is the value of main:: at compile time. |
|
|
131 | |
|
|
132 | |
|
|
133 | ############################################################################### |
|
|
134 | # TO ENABLE CACHEING UNCOMMENT THE CACHEING CODE AND COMMENT OUT THE STANDARD LOADING CODE |
|
|
135 | # On webwork3 cached code is .2 seconds faster than non-cached code for an existing child. |
|
|
136 | |
|
|
137 | # CACHING CODE: |
|
|
138 | # $translator->pre_load_macro_files($WeBWorK::PG::Local::safeCache, $ce->{pg}->{directories}->{macros}, |
|
|
139 | # 'PG.pl', 'dangerousMacros.pl','IO.pl','PGbasicmacros.pl','PGanswermacros.pl'); |
|
|
140 | |
|
|
141 | # STANDARD LOADING CODE: |
| 105 | foreach (qw(IO.pl PG.pl dangerousMacros.pl)) { |
142 | foreach (qw(IO.pl PG.pl dangerousMacros.pl)) { |
| 106 | my $macroPath = $ce->{pg}->{directories}->{macros} . "/$_"; |
143 | my $macroPath = $ce->{pg}->{directories}->{macros} . "/$_"; |
| 107 | my $err = $translator->unrestricted_load($macroPath); |
144 | my $err = $translator->unrestricted_load($macroPath); |
| 108 | warn "Error while loading $macroPath: $err" if $err; |
145 | warn "Error while loading $macroPath: |$err|" if $err; |
| 109 | } |
146 | } |
| 110 | |
147 | ############################################################################### |
|
|
148 | |
| 111 | # set the opcode mask (using default values) |
149 | # set the opcode mask (using default values) |
| 112 | #warn "PG: setting the opcode mask (using default values)\n"; |
150 | #warn "PG: setting the opcode mask (using default values)\n"; |
| 113 | $translator->set_mask(); |
151 | $translator->set_mask(); |
| 114 | |
152 | |
| 115 | # store the problem source |
153 | # store the problem source |
| … | |
… | |
| 120 | eval { $translator->source_string(readFile($sourceFile)) }; |
158 | eval { $translator->source_string(readFile($sourceFile)) }; |
| 121 | if ($@) { |
159 | if ($@) { |
| 122 | # well, we couldn't get the problem source, for some reason. |
160 | # well, we couldn't get the problem source, for some reason. |
| 123 | return bless { |
161 | return bless { |
| 124 | translator => $translator, |
162 | translator => $translator, |
| 125 | head_text => "", |
163 | head_text => "", |
| 126 | body_text => <<EOF, |
164 | body_text => <<EOF, |
| 127 | WeBWorK::Utils::readFile($sourceFile) says: |
165 | WeBWorK::Utils::readFile($sourceFile) says: |
| 128 | $@ |
166 | $@ |
| 129 | EOF |
167 | EOF |
| 130 | answers => {}, |
168 | answers => {}, |
| 131 | result => {}, |
169 | result => {}, |
| 132 | state => {}, |
170 | state => {}, |