From 72fa0b1128357f3c0b471fddc5d0ff77766a2ea7 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Thu, 27 Oct 2005 03:19:06 +0000 Subject: [PATCH] Separated the abstraction of a file handle, from its implementation and parsing. Added a test for the FILE HANDLE command. --- po/en_GB.po | 137 ++++++++-------- po/pspp.pot | 137 ++++++++-------- src/ChangeLog | 9 ++ src/Makefile.am | 7 +- src/dfm-read.c | 2 +- src/file-handle-def.c | 301 +++++++++++++++++++++++++++++++++++ src/file-handle-def.h | 97 +++++++++++ src/file-handle.h | 15 +- src/file-handle.q | 271 +++---------------------------- tests/Makefile.am | 1 + tests/command/file-handle.sh | 95 +++++++++++ 11 files changed, 664 insertions(+), 408 deletions(-) create mode 100644 src/file-handle-def.c create mode 100644 src/file-handle-def.h create mode 100755 tests/command/file-handle.sh diff --git a/po/en_GB.po b/po/en_GB.po index bb5b54bb..968681d7 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PSPP 0.3.1\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2005-10-25 17:56+0800\n" +"POT-Creation-Date: 2005-10-27 10:56+0800\n" "PO-Revision-Date: 2004-01-23 13:04+0800\n" "Last-Translator: John Darrington \n" "Language-Team: John Darrington \n" @@ -233,7 +233,7 @@ msgid "Source variable count (%u) does not match target variable count (%u)." msgstr "" #: src/autorecode.c:143 src/command.c:797 src/compute.c:280 src/do-if.c:256 -#: src/file-handle.q:142 src/lexer.c:438 src/loop.c:244 src/matrix-data.c:532 +#: src/file-handle.q:83 src/lexer.c:438 src/loop.c:244 src/matrix-data.c:532 #: src/print.c:338 src/print.c:1049 src/recode.c:410 src/sel-if.c:57 #: src/sel-if.c:134 src/vector.c:197 msgid "expecting end of command" @@ -566,7 +566,7 @@ msgstr "" #: src/crosstabs.q:1109 src/crosstabs.q:1136 src/crosstabs.q:1156 #: src/crosstabs.q:1178 src/examine.q:1134 src/frequencies.q:1143 -#: src/frequencies.q:1264 src/sysfile-info.c:517 src/vfm.c:812 +#: src/frequencies.q:1264 src/sysfile-info.c:518 src/vfm.c:812 msgid "Value" msgstr "" @@ -1015,7 +1015,7 @@ msgid "" msgstr "" #: src/data-list.c:788 src/data-list.c:912 src/descript.c:886 src/print.c:800 -#: src/sysfile-info.c:138 src/sysfile-info.c:372 src/vfm.c:811 +#: src/sysfile-info.c:139 src/sysfile-info.c:373 src/vfm.c:811 msgid "Variable" msgstr "" @@ -1768,46 +1768,31 @@ msgstr "" msgid "%s is a PSPP extension." msgstr "" -#: src/file-handle.q:127 +#: src/file-handle.q:68 #, c-format msgid "" "File handle %s already refers to file %s. File handles cannot be redefined " "within a session." msgstr "" -#: src/file-handle.q:148 +#: src/file-handle.q:89 msgid "The FILE HANDLE required subcommand NAME is not present." msgstr "" -#: src/file-handle.q:167 +#: src/file-handle.q:113 msgid "" "Fixed-length records were specified on /RECFORM, but record length was not " "specified on /LRECL. Assuming 1024-character records." msgstr "" -#: src/file-handle.q:174 +#: src/file-handle.q:120 #, c-format msgid "" "Record length (%ld) must be at least one byte. 1-character records will be " "assumed." msgstr "" -#: src/file-handle.q:274 -#, c-format -msgid "Can't open %s as a %s because it is already open as a %s" -msgstr "" - -#: src/file-handle.q:281 -#, c-format -msgid "Can't open %s as a %s for %s because it is already open for %s" -msgstr "" - -#: src/file-handle.q:289 -#, c-format -msgid "Can't re-open %s as a %s for %s" -msgstr "" - -#: src/file-handle.q:342 +#: src/file-handle.q:157 msgid "expecting a file name or handle name" msgstr "" @@ -2522,7 +2507,7 @@ msgstr "" msgid "HTML output driver: %s: %s" msgstr "" -#: src/html.c:421 src/list.q:257 +#: src/html.c:421 src/list.q:256 #, c-format msgid "Cannot open first page on HTML device %s." msgstr "" @@ -2681,11 +2666,11 @@ msgstr "" msgid "The step value %ld is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:202 +#: src/list.q:201 msgid "`/FORMAT WEIGHT' specified, but weighting is not on." msgstr "" -#: src/list.q:445 +#: src/list.q:444 msgid "Line" msgstr "" @@ -3807,6 +3792,18 @@ msgstr "" msgid "Residual" msgstr "" +#: src/regression.q:322 +msgid "Model" +msgstr "" + +#: src/regression.q:323 +msgid "Covariances" +msgstr "" + +#: src/regression.q:339 +msgid "Coefficient Correlations" +msgstr "" + #: src/rename-vars.c:49 msgid "" "RENAME VARS may not be used after TEMPORARY. Temporary transformations will " @@ -4145,7 +4142,7 @@ msgstr "" msgid "DEC Kanji" msgstr "" -#: src/sfm-read.c:556 src/sysfile-info.c:118 +#: src/sfm-read.c:556 src/sysfile-info.c:119 msgid "Unknown" msgstr "" @@ -4401,7 +4398,7 @@ msgstr "" msgid "Buffer limit must be at least 2." msgstr "" -#: src/sort.c:461 +#: src/sort.c:462 #, c-format msgid "" "Out of memory. Could not allocate room for minimum of %d cases of %d bytes " @@ -4416,135 +4413,135 @@ msgstr "" msgid "`)' expected." msgstr "" -#: src/sysfile-info.c:99 +#: src/sysfile-info.c:100 msgid "File:" msgstr "" -#: src/sysfile-info.c:101 +#: src/sysfile-info.c:102 msgid "Label:" msgstr "" -#: src/sysfile-info.c:105 +#: src/sysfile-info.c:106 msgid "No label." msgstr "" -#: src/sysfile-info.c:108 +#: src/sysfile-info.c:109 msgid "Created:" msgstr "" -#: src/sysfile-info.c:111 +#: src/sysfile-info.c:112 msgid "Endian:" msgstr "" -#: src/sysfile-info.c:112 +#: src/sysfile-info.c:113 msgid "Big." msgstr "" -#: src/sysfile-info.c:112 +#: src/sysfile-info.c:113 msgid "Little." msgstr "" -#: src/sysfile-info.c:113 +#: src/sysfile-info.c:114 msgid "Variables:" msgstr "" -#: src/sysfile-info.c:116 +#: src/sysfile-info.c:117 msgid "Cases:" msgstr "" -#: src/sysfile-info.c:119 +#: src/sysfile-info.c:120 msgid "Type:" msgstr "" -#: src/sysfile-info.c:120 +#: src/sysfile-info.c:121 msgid "System File." msgstr "" -#: src/sysfile-info.c:121 +#: src/sysfile-info.c:122 msgid "Weight:" msgstr "" -#: src/sysfile-info.c:125 +#: src/sysfile-info.c:126 msgid "Not weighted." msgstr "" -#: src/sysfile-info.c:127 +#: src/sysfile-info.c:128 msgid "Mode:" msgstr "" -#: src/sysfile-info.c:129 +#: src/sysfile-info.c:130 #, c-format msgid "Compression %s." msgstr "" -#: src/sysfile-info.c:129 +#: src/sysfile-info.c:130 msgid "on" msgstr "" -#: src/sysfile-info.c:129 +#: src/sysfile-info.c:130 msgid "off" msgstr "" -#: src/sysfile-info.c:139 src/sysfile-info.c:377 +#: src/sysfile-info.c:140 src/sysfile-info.c:378 msgid "Description" msgstr "" -#: src/sysfile-info.c:140 src/sysfile-info.c:375 +#: src/sysfile-info.c:141 src/sysfile-info.c:376 msgid "Position" msgstr "" -#: src/sysfile-info.c:198 +#: src/sysfile-info.c:199 msgid "The active file does not have a file label." msgstr "" -#: src/sysfile-info.c:201 +#: src/sysfile-info.c:202 msgid "File label:" msgstr "" -#: src/sysfile-info.c:263 +#: src/sysfile-info.c:264 msgid "No variables to display." msgstr "" -#: src/sysfile-info.c:282 +#: src/sysfile-info.c:283 msgid "Macros not supported." msgstr "" -#: src/sysfile-info.c:292 +#: src/sysfile-info.c:293 msgid "The active file dictionary does not contain any documents." msgstr "" -#: src/sysfile-info.c:301 +#: src/sysfile-info.c:302 msgid "Documents in the active file:" msgstr "" -#: src/sysfile-info.c:379 src/sysfile-info.c:518 src/vfm.c:813 +#: src/sysfile-info.c:380 src/sysfile-info.c:519 src/vfm.c:813 msgid "Label" msgstr "" -#: src/sysfile-info.c:451 +#: src/sysfile-info.c:452 #, c-format msgid "Format: %s" msgstr "" -#: src/sysfile-info.c:458 +#: src/sysfile-info.c:459 #, c-format msgid "Print Format: %s" msgstr "" -#: src/sysfile-info.c:461 +#: src/sysfile-info.c:462 #, c-format msgid "Write Format: %s" msgstr "" -#: src/sysfile-info.c:473 +#: src/sysfile-info.c:474 msgid "Missing Values: " msgstr "" -#: src/sysfile-info.c:574 +#: src/sysfile-info.c:575 msgid "No vectors defined." msgstr "" -#: src/sysfile-info.c:589 +#: src/sysfile-info.c:590 msgid "Vector" msgstr "" @@ -4742,45 +4739,45 @@ msgstr "" msgid "Truncating variable label to 255 characters." msgstr "" -#: src/vars-atr.c:132 +#: src/vars-atr.c:126 msgid "Variable name cannot be empty string." msgstr "" -#: src/vars-atr.c:138 +#: src/vars-atr.c:132 #, c-format msgid "Variable name %s exceeds %d-character limit." msgstr "" -#: src/vars-atr.c:147 +#: src/vars-atr.c:141 #, c-format msgid "Character `%c' (in %s) may not appear in a variable name." msgstr "" -#: src/vars-atr.c:156 +#: src/vars-atr.c:150 #, c-format msgid "" "Character `%c' (in %s), may not appear as the first character in a variable " "name." msgstr "" -#: src/vars-atr.c:165 +#: src/vars-atr.c:159 #, c-format msgid "%s may not be used as a variable name because it is a reserved word." msgstr "" -#: src/vars-atr.c:260 +#: src/vars-atr.c:254 msgid "Variable suffix too large." msgstr "" -#: src/vars-atr.c:301 +#: src/vars-atr.c:295 msgid "ordinary" msgstr "" -#: src/vars-atr.c:303 +#: src/vars-atr.c:297 msgid "system" msgstr "" -#: src/vars-atr.c:305 +#: src/vars-atr.c:299 msgid "scratch" msgstr "" diff --git a/po/pspp.pot b/po/pspp.pot index a0e676a7..63bc73b4 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2005-10-25 17:56+0800\n" +"POT-Creation-Date: 2005-10-27 10:56+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -234,7 +234,7 @@ msgid "Source variable count (%u) does not match target variable count (%u)." msgstr "" #: src/autorecode.c:143 src/command.c:797 src/compute.c:280 src/do-if.c:256 -#: src/file-handle.q:142 src/lexer.c:438 src/loop.c:244 src/matrix-data.c:532 +#: src/file-handle.q:83 src/lexer.c:438 src/loop.c:244 src/matrix-data.c:532 #: src/print.c:338 src/print.c:1049 src/recode.c:410 src/sel-if.c:57 #: src/sel-if.c:134 src/vector.c:197 msgid "expecting end of command" @@ -567,7 +567,7 @@ msgstr "" #: src/crosstabs.q:1109 src/crosstabs.q:1136 src/crosstabs.q:1156 #: src/crosstabs.q:1178 src/examine.q:1134 src/frequencies.q:1143 -#: src/frequencies.q:1264 src/sysfile-info.c:517 src/vfm.c:812 +#: src/frequencies.q:1264 src/sysfile-info.c:518 src/vfm.c:812 msgid "Value" msgstr "" @@ -1016,7 +1016,7 @@ msgid "" msgstr "" #: src/data-list.c:788 src/data-list.c:912 src/descript.c:886 src/print.c:800 -#: src/sysfile-info.c:138 src/sysfile-info.c:372 src/vfm.c:811 +#: src/sysfile-info.c:139 src/sysfile-info.c:373 src/vfm.c:811 msgid "Variable" msgstr "" @@ -1769,46 +1769,31 @@ msgstr "" msgid "%s is a PSPP extension." msgstr "" -#: src/file-handle.q:127 +#: src/file-handle.q:68 #, c-format msgid "" "File handle %s already refers to file %s. File handles cannot be redefined " "within a session." msgstr "" -#: src/file-handle.q:148 +#: src/file-handle.q:89 msgid "The FILE HANDLE required subcommand NAME is not present." msgstr "" -#: src/file-handle.q:167 +#: src/file-handle.q:113 msgid "" "Fixed-length records were specified on /RECFORM, but record length was not " "specified on /LRECL. Assuming 1024-character records." msgstr "" -#: src/file-handle.q:174 +#: src/file-handle.q:120 #, c-format msgid "" "Record length (%ld) must be at least one byte. 1-character records will be " "assumed." msgstr "" -#: src/file-handle.q:274 -#, c-format -msgid "Can't open %s as a %s because it is already open as a %s" -msgstr "" - -#: src/file-handle.q:281 -#, c-format -msgid "Can't open %s as a %s for %s because it is already open for %s" -msgstr "" - -#: src/file-handle.q:289 -#, c-format -msgid "Can't re-open %s as a %s for %s" -msgstr "" - -#: src/file-handle.q:342 +#: src/file-handle.q:157 msgid "expecting a file name or handle name" msgstr "" @@ -2523,7 +2508,7 @@ msgstr "" msgid "HTML output driver: %s: %s" msgstr "" -#: src/html.c:421 src/list.q:257 +#: src/html.c:421 src/list.q:256 #, c-format msgid "Cannot open first page on HTML device %s." msgstr "" @@ -2682,11 +2667,11 @@ msgstr "" msgid "The step value %ld is less than 1. The value is being reset to 1." msgstr "" -#: src/list.q:202 +#: src/list.q:201 msgid "`/FORMAT WEIGHT' specified, but weighting is not on." msgstr "" -#: src/list.q:445 +#: src/list.q:444 msgid "Line" msgstr "" @@ -3808,6 +3793,18 @@ msgstr "" msgid "Residual" msgstr "" +#: src/regression.q:322 +msgid "Model" +msgstr "" + +#: src/regression.q:323 +msgid "Covariances" +msgstr "" + +#: src/regression.q:339 +msgid "Coefficient Correlations" +msgstr "" + #: src/rename-vars.c:49 msgid "" "RENAME VARS may not be used after TEMPORARY. Temporary transformations will " @@ -4146,7 +4143,7 @@ msgstr "" msgid "DEC Kanji" msgstr "" -#: src/sfm-read.c:556 src/sysfile-info.c:118 +#: src/sfm-read.c:556 src/sysfile-info.c:119 msgid "Unknown" msgstr "" @@ -4402,7 +4399,7 @@ msgstr "" msgid "Buffer limit must be at least 2." msgstr "" -#: src/sort.c:461 +#: src/sort.c:462 #, c-format msgid "" "Out of memory. Could not allocate room for minimum of %d cases of %d bytes " @@ -4417,135 +4414,135 @@ msgstr "" msgid "`)' expected." msgstr "" -#: src/sysfile-info.c:99 +#: src/sysfile-info.c:100 msgid "File:" msgstr "" -#: src/sysfile-info.c:101 +#: src/sysfile-info.c:102 msgid "Label:" msgstr "" -#: src/sysfile-info.c:105 +#: src/sysfile-info.c:106 msgid "No label." msgstr "" -#: src/sysfile-info.c:108 +#: src/sysfile-info.c:109 msgid "Created:" msgstr "" -#: src/sysfile-info.c:111 +#: src/sysfile-info.c:112 msgid "Endian:" msgstr "" -#: src/sysfile-info.c:112 +#: src/sysfile-info.c:113 msgid "Big." msgstr "" -#: src/sysfile-info.c:112 +#: src/sysfile-info.c:113 msgid "Little." msgstr "" -#: src/sysfile-info.c:113 +#: src/sysfile-info.c:114 msgid "Variables:" msgstr "" -#: src/sysfile-info.c:116 +#: src/sysfile-info.c:117 msgid "Cases:" msgstr "" -#: src/sysfile-info.c:119 +#: src/sysfile-info.c:120 msgid "Type:" msgstr "" -#: src/sysfile-info.c:120 +#: src/sysfile-info.c:121 msgid "System File." msgstr "" -#: src/sysfile-info.c:121 +#: src/sysfile-info.c:122 msgid "Weight:" msgstr "" -#: src/sysfile-info.c:125 +#: src/sysfile-info.c:126 msgid "Not weighted." msgstr "" -#: src/sysfile-info.c:127 +#: src/sysfile-info.c:128 msgid "Mode:" msgstr "" -#: src/sysfile-info.c:129 +#: src/sysfile-info.c:130 #, c-format msgid "Compression %s." msgstr "" -#: src/sysfile-info.c:129 +#: src/sysfile-info.c:130 msgid "on" msgstr "" -#: src/sysfile-info.c:129 +#: src/sysfile-info.c:130 msgid "off" msgstr "" -#: src/sysfile-info.c:139 src/sysfile-info.c:377 +#: src/sysfile-info.c:140 src/sysfile-info.c:378 msgid "Description" msgstr "" -#: src/sysfile-info.c:140 src/sysfile-info.c:375 +#: src/sysfile-info.c:141 src/sysfile-info.c:376 msgid "Position" msgstr "" -#: src/sysfile-info.c:198 +#: src/sysfile-info.c:199 msgid "The active file does not have a file label." msgstr "" -#: src/sysfile-info.c:201 +#: src/sysfile-info.c:202 msgid "File label:" msgstr "" -#: src/sysfile-info.c:263 +#: src/sysfile-info.c:264 msgid "No variables to display." msgstr "" -#: src/sysfile-info.c:282 +#: src/sysfile-info.c:283 msgid "Macros not supported." msgstr "" -#: src/sysfile-info.c:292 +#: src/sysfile-info.c:293 msgid "The active file dictionary does not contain any documents." msgstr "" -#: src/sysfile-info.c:301 +#: src/sysfile-info.c:302 msgid "Documents in the active file:" msgstr "" -#: src/sysfile-info.c:379 src/sysfile-info.c:518 src/vfm.c:813 +#: src/sysfile-info.c:380 src/sysfile-info.c:519 src/vfm.c:813 msgid "Label" msgstr "" -#: src/sysfile-info.c:451 +#: src/sysfile-info.c:452 #, c-format msgid "Format: %s" msgstr "" -#: src/sysfile-info.c:458 +#: src/sysfile-info.c:459 #, c-format msgid "Print Format: %s" msgstr "" -#: src/sysfile-info.c:461 +#: src/sysfile-info.c:462 #, c-format msgid "Write Format: %s" msgstr "" -#: src/sysfile-info.c:473 +#: src/sysfile-info.c:474 msgid "Missing Values: " msgstr "" -#: src/sysfile-info.c:574 +#: src/sysfile-info.c:575 msgid "No vectors defined." msgstr "" -#: src/sysfile-info.c:589 +#: src/sysfile-info.c:590 msgid "Vector" msgstr "" @@ -4743,45 +4740,45 @@ msgstr "" msgid "Truncating variable label to 255 characters." msgstr "" -#: src/vars-atr.c:132 +#: src/vars-atr.c:126 msgid "Variable name cannot be empty string." msgstr "" -#: src/vars-atr.c:138 +#: src/vars-atr.c:132 #, c-format msgid "Variable name %s exceeds %d-character limit." msgstr "" -#: src/vars-atr.c:147 +#: src/vars-atr.c:141 #, c-format msgid "Character `%c' (in %s) may not appear in a variable name." msgstr "" -#: src/vars-atr.c:156 +#: src/vars-atr.c:150 #, c-format msgid "" "Character `%c' (in %s), may not appear as the first character in a variable " "name." msgstr "" -#: src/vars-atr.c:165 +#: src/vars-atr.c:159 #, c-format msgid "%s may not be used as a variable name because it is a reserved word." msgstr "" -#: src/vars-atr.c:260 +#: src/vars-atr.c:254 msgid "Variable suffix too large." msgstr "" -#: src/vars-atr.c:301 +#: src/vars-atr.c:295 msgid "ordinary" msgstr "" -#: src/vars-atr.c:303 +#: src/vars-atr.c:297 msgid "system" msgstr "" -#: src/vars-atr.c:305 +#: src/vars-atr.c:299 msgid "scratch" msgstr "" diff --git a/src/ChangeLog b/src/ChangeLog index 7e5f4057..ce26823e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +Thu Oct 27 11:16:53 WST 2005 John Darrington + + Separated the definition of a file handle object from the stuff + pertaining to the FILE HANDLE command. + + * file-handle-def.[ch]: New files. + + * dfm-read.c file-handle.h file-handle.q + Tue Oct 25 21:56:23 2005 Ben Pfaff Fix up potential overflows in size calculations by replacing diff --git a/src/Makefile.am b/src/Makefile.am index 87ecce90..4d24e67d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,11 +49,12 @@ command.h compute.c copyleft.c copyleft.h count.c data-in.c data-in.h \ data-list.c data-list.h data-out.c date.c debug-print.h descript.c \ devind.c devind.h dfm-read.c dfm-read.h dfm-write.c dfm-write.h \ dictionary.c dictionary.h do-if.c do-ifP.h echo.c error.c error.h \ -factor_stats.c factor_stats.h file-handle.h file-type.c filename.c \ -filename.h flip.c font.h format.c format-prs.c format.def format.h formats.c get.c \ +factor_stats.c factor_stats.h file-handle-def.c file-handle-def.h \ +file-handle.h file-type.c filename.c filename.h flip.c font.h format.c \ +format-prs.c format.def format.h formats.c get.c \ getl.c getl.h glob.c glob.h groff-font.c group.c group.h group_proc.h \ hash.c hash.h histogram.c histogram.h html.c htmlP.h include.c \ -inpt-pgm.c lexer.c lexer.h lex-def.h lex-def.c levene.c levene.h linked-list.c \ +inpt-pgm.c lexer.c lexer.h lex-def.h lex-def.c levene.c levene.h linked-list.c \ linked-list.h log.h loop.c magic.c magic.h main.c main.h matrix-data.c \ mis-val.c misc.c misc.h missing-values.c missing-values.h \ modify-vars.c moments.c moments.h numeric.c output.c output.h \ diff --git a/src/dfm-read.c b/src/dfm-read.c index 2f17d419..238b8080 100644 --- a/src/dfm-read.c +++ b/src/dfm-read.c @@ -26,7 +26,7 @@ #include "alloc.h" #include "command.h" #include "error.h" -#include "file-handle.h" +#include "file-handle-def.h" #include "filename.h" #include "getl.h" #include "lexer.h" diff --git a/src/file-handle-def.c b/src/file-handle-def.c new file mode 100644 index 00000000..5dd13e54 --- /dev/null +++ b/src/file-handle-def.c @@ -0,0 +1,301 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "file-handle.h" +#include "error.h" +#include +#include +#include +#include "alloc.h" +#include "filename.h" +#include "command.h" +#include "getl.h" +#include "error.h" +#include "magic.h" +#include "var.h" +#include "file-handle-def.h" + +#include "gettext.h" + +#define _(msgid) gettext (msgid) + +/* (headers) */ + +/* File handle. */ +struct file_handle + { + struct file_handle *next; /* Next in global list. */ + char *name; /* File handle identifier. */ + char *filename; /* Filename as provided by user. */ + struct file_identity *identity; /* For checking file identity. */ + struct file_locator where; /* Used for reporting error messages. */ + enum file_handle_mode mode; /* File mode. */ + size_t length; /* Length of fixed-format records. */ + size_t tab_width; /* Tab width, 0=do not expand tabs. */ + + int open_cnt; /* 0=not open, otherwise # of openers. */ + const char *type; /* If open, type of file. */ + char open_mode[3]; /* "[rw][se]". */ + void *aux; /* Aux data pointer for owner if any. */ + }; + + +static struct file_handle *file_handles; + + +struct file_handle * +get_handle_with_name (const char *handle_name) +{ + struct file_handle *iter; + + for (iter = file_handles; iter != NULL; iter = iter->next) + if (!strcasecmp (handle_name, iter->name)) + return iter; + return NULL; +} + +struct file_handle * +get_handle_for_filename (const char *filename) +{ + struct file_identity *identity; + struct file_handle *iter; + + /* First check for a file with the same identity. */ + identity = fn_get_identity (filename); + if (identity != NULL) + { + for (iter = file_handles; iter != NULL; iter = iter->next) + if (iter->identity != NULL + && !fn_compare_file_identities (identity, iter->identity)) + { + fn_free_identity (identity); + return iter; + } + fn_free_identity (identity); + } + + /* Then check for a file with the same name. */ + for (iter = file_handles; iter != NULL; iter = iter->next) + if (!strcmp (filename, iter->filename)) + return iter; + + return NULL; +} + + +/* File handle functions. */ + +struct file_handle * +create_file_handle_with_defaults (const char *handle_name, + const char *filename) +{ + return create_file_handle (handle_name, filename, + MODE_TEXT,1024, 4); +} + + +/* Creates and returns a new file handle with the given values + and defaults for other values. Adds the created file handle + to the global list. */ +struct file_handle * +create_file_handle (const char *handle_name, const char *filename, + enum file_handle_mode mode, + size_t length, + size_t tab_width + ) +{ + struct file_handle *handle; + + /* Create and initialize file handle. */ + handle = xmalloc (sizeof *handle); + handle->next = file_handles; + handle->name = xstrdup (handle_name); + handle->filename = xstrdup (filename); + handle->identity = fn_get_identity (filename); + handle->where.filename = handle->filename; + handle->where.line_number = 0; + handle->mode = mode; + handle->length = length; + handle->tab_width = tab_width; + handle->open_cnt = 0; + handle->type = NULL; + handle->aux = NULL; + file_handles = handle; + + return handle; +} + +void +destroy_file_handle(void *fh_, void *aux UNUSED) +{ + struct file_handle *fh = fh_; + free (fh->name); + free (fh->filename); + fn_free_identity (fh->identity); + free (fh); +} + +static const char * +mode_name (const char *mode) +{ + assert (mode != NULL); + assert (mode[0] == 'r' || mode[0] == 'w'); + + return mode[0] == 'r' ? "reading" : "writing"; +} + + +/* Tries to open handle H with the given TYPE and MODE. + + TYPE is the sort of file, e.g. "system file". Only one given + type of access is allowed on a given file handle at once. + + MODE combines the read or write mode with the sharing mode. + The first character is 'r' for read, 'w' for write. The + second character is 's' to permit sharing, 'e' to require + exclusive access. + + Returns the address of a void * that the caller can use for + data specific to the file handle if successful, or a null + pointer on failure. For exclusive access modes the void * + will always be a null pointer at return. In shared access + modes the void * will necessarily be null only if no other + sharers are active. + + If successful, a reference to type is retained, so it should + probably be a string literal. */ +void ** +fh_open (struct file_handle *h, const char *type, const char *mode) +{ + assert (h != NULL); + assert (type != NULL); + assert (mode != NULL); + assert (mode[0] == 'r' || mode[0] == 'w'); + assert (mode[1] == 's' || mode[1] == 'e'); + assert (mode[2] == '\0'); + + if (h->open_cnt != 0) + { + if (strcmp (h->type, type)) + { + msg (SE, _("Can't open %s as a %s because it is " + "already open as a %s"), + handle_get_name (h), type, h->type); + return NULL; + } + else if (strcmp (h->open_mode, mode)) + { + msg (SE, _("Can't open %s as a %s for %s because it is " + "already open for %s"), + handle_get_name (h), type, + mode_name (mode), mode_name (h->open_mode)); + return NULL; + } + else if (h->open_mode[1] == 'e') + { + msg (SE, _("Can't re-open %s as a %s for %s"), + handle_get_name (h), type, mode_name (mode)); + return NULL; + } + } + else + { + h->type = type; + strcpy (h->open_mode, mode); + assert (h->aux == NULL); + } + h->open_cnt++; + + return &h->aux; +} + +/* Closes file handle H, which must have been open for the + specified TYPE and MODE of access provided to fh_open(). + Returns zero if the file is now closed, nonzero if it is still + open due to another reference. */ +int +fh_close (struct file_handle *h, const char *type, const char *mode) +{ + assert (h != NULL); + assert (h->open_cnt > 0); + assert (type != NULL); + assert (!strcmp (type, h->type)); + assert (mode != NULL); + assert (!strcmp (mode, h->open_mode)); + + h->open_cnt--; + if (h->open_cnt == 0) + { + h->type = NULL; + h->aux = NULL; + } + return h->open_cnt; +} + + + + +/* Returns the identifier of file HANDLE. If HANDLE was created + by referring to a filename instead of a handle name, returns + the filename, enclosed in double quotes. Return value is + owned by the file handle. + + Useful for printing error messages about use of file handles. */ +const char * +handle_get_name (const struct file_handle *handle) +{ + assert (handle != NULL); + return handle->name; +} + +/* Returns the name of the file associated with HANDLE. */ +const char * +handle_get_filename (const struct file_handle *handle) +{ + assert (handle != NULL); + return handle->filename; +} + +/* Returns the mode of HANDLE. */ +enum file_handle_mode +handle_get_mode (const struct file_handle *handle) +{ + assert (handle != NULL); + return handle->mode; +} + +/* Returns the width of a logical record on HANDLE. */ +size_t +handle_get_record_width (const struct file_handle *handle) +{ + assert (handle != NULL); + return handle->length; +} + +/* Returns the number of characters per tab stop for HANDLE, or + zero if tabs are not to be expanded. Applicable only to + MODE_TEXT files. */ +size_t +handle_get_tab_width (const struct file_handle *handle) +{ + assert (handle != NULL); + return handle->tab_width; +} + diff --git a/src/file-handle-def.h b/src/file-handle-def.h new file mode 100644 index 00000000..930477a9 --- /dev/null +++ b/src/file-handle-def.h @@ -0,0 +1,97 @@ +/* PSPP - computes sample statistics. + Copyright (C) 1997-9, 2000,2005 Free Software Foundation, Inc. + Written by Ben Pfaff . + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef FILE_HANDLE_DEF_H +#define FILE_HANDLE_DEF_H + +#include + +/* File modes. */ +enum file_handle_mode + { + MODE_TEXT, /* New-line delimited lines. */ + MODE_BINARY /* Fixed-length records. */ + }; + +struct file_handle *create_file_handle_with_defaults (const char *handle_name, + const char *filename); + +struct file_handle *create_file_handle (const char *handle_name, + const char *filename, + enum file_handle_mode mode, + size_t length, + size_t tab_width + ); + + + +struct file_handle * +get_handle_with_name (const char *handle_name) ; + +struct file_handle * +get_handle_for_filename (const char *filename); + +const char *handle_get_name (const struct file_handle *handle); + +/* Returns the name of the file associated with HANDLE. */ +const char *handle_get_filename (const struct file_handle *handle) ; + + + +/* Returns the mode of HANDLE. */ +enum file_handle_mode handle_get_mode (const struct file_handle *handle) ; + +/* Returns the width of a logical record on HANDLE. */ +size_t handle_get_record_width (const struct file_handle *handle); + + +/* Returns the number of characters per tab stop for HANDLE, or + zero if tabs are not to be expanded. Applicable only to + MODE_TEXT files. */ +size_t handle_get_tab_width (const struct file_handle *handle); + + + +void destroy_file_handle(void *fh_, void *aux UNUSED); + + +/* Tries to open handle H with the given TYPE and MODE. + + TYPE is the sort of file, e.g. "system file". Only one given + type of access is allowed on a given file handle at once. + + MODE combines the read or write mode with the sharing mode. + The first character is 'r' for read, 'w' for write. The + second character is 's' to permit sharing, 'e' to require + exclusive access. + + Returns the address of a void * that the caller can use for + data specific to the file handle if successful, or a null + pointer on failure. For exclusive access modes the void * + will always be a null pointer at return. In shared access + modes the void * will necessarily be null only if no other + sharers are active. + + If successful, a reference to type is retained, so it should + probably be a string literal. */ + +void ** fh_open (struct file_handle *h, const char *type, const char *mode) ; + + +#endif diff --git a/src/file-handle.h b/src/file-handle.h index d7c14e99..eab80521 100644 --- a/src/file-handle.h +++ b/src/file-handle.h @@ -23,19 +23,14 @@ /* File handles. */ #include - -/* File modes. */ -enum file_handle_mode - { - MODE_TEXT, /* New-line delimited lines. */ - MODE_BINARY /* Fixed-length records. */ - }; +#include "file-handle-def.h" void fh_init(void); void fh_done(void); + /* Parsing handles. */ struct file_handle *fh_parse (void); @@ -44,11 +39,5 @@ struct file_handle *fh_parse (void); void **fh_open (struct file_handle *, const char *type, const char *mode); int fh_close (struct file_handle *, const char *type, const char *mode); -/* Handle info. */ -const char *handle_get_name (const struct file_handle *); -const char *handle_get_filename (const struct file_handle *); -enum file_handle_mode handle_get_mode (const struct file_handle *); -size_t handle_get_record_width (const struct file_handle *); -size_t handle_get_tab_width (const struct file_handle *); #endif /* !file_handle.h */ diff --git a/src/file-handle.q b/src/file-handle.q index 6ea731ef..98b2354c 100644 --- a/src/file-handle.q +++ b/src/file-handle.q @@ -31,34 +31,13 @@ #include "magic.h" #include "var.h" #include "linked-list.h" +#include "file-handle-def.h" #include "gettext.h" #define _(msgid) gettext (msgid) /* (headers) */ -/* File handle. */ -struct file_handle - { - struct file_handle *next; /* Next in global list. */ - char *name; /* File handle identifier. */ - char *filename; /* Filename as provided by user. */ - struct file_identity *identity; /* For checking file identity. */ - struct file_locator where; /* Used for reporting error messages. */ - enum file_handle_mode mode; /* File mode. */ - size_t length; /* Length of fixed-format records. */ - size_t tab_width; /* Tab width, 0=do not expand tabs. */ - - int open_cnt; /* 0=not open, otherwise # of openers. */ - const char *type; /* If open, type of file. */ - char open_mode[3]; /* "[rw][se]". */ - void *aux; /* Aux data pointer for owner if any. */ - }; - -static struct file_handle *file_handles; - -static struct file_handle *create_file_handle (const char *handle_name, - const char *filename); /* (specification) "FILE HANDLE" (fh_): @@ -70,44 +49,6 @@ static struct file_handle *create_file_handle (const char *handle_name, /* (declarations) */ /* (functions) */ -static struct file_handle * -get_handle_with_name (const char *handle_name) -{ - struct file_handle *iter; - - for (iter = file_handles; iter != NULL; iter = iter->next) - if (!strcasecmp (handle_name, iter->name)) - return iter; - return NULL; -} - -static struct file_handle * -get_handle_for_filename (const char *filename) -{ - struct file_identity *identity; - struct file_handle *iter; - - /* First check for a file with the same identity. */ - identity = fn_get_identity (filename); - if (identity != NULL) - { - for (iter = file_handles; iter != NULL; iter = iter->next) - if (iter->identity != NULL - && !fn_compare_file_identities (identity, iter->identity)) - { - fn_free_identity (identity); - return iter; - } - fn_free_identity (identity); - } - - /* Then check for a file with the same name. */ - for (iter = file_handles; iter != NULL; iter = iter->next) - if (!strcmp (filename, iter->filename)) - return iter; - - return NULL; -} int cmd_file_handle (void) @@ -126,7 +67,7 @@ cmd_file_handle (void) { msg (SE, _("File handle %s already refers to file %s. " "File handles cannot be redefined within a session."), - handle_name, handle->filename); + handle_name, handle_get_filename(handle)); return CMD_FAILURE; } @@ -150,180 +91,54 @@ cmd_file_handle (void) goto lossage; } - handle = create_file_handle (handle_name, cmd.s_name); + + enum file_handle_mode mode = MODE_TEXT; + size_t length = 1024; + size_t tab_width = 4; + + switch (cmd.mode) { case FH_CHARACTER: - handle->mode = MODE_TEXT; + mode = MODE_TEXT; if (cmd.sbc_tabwidth) - handle->tab_width = cmd.n_tabwidth[0]; + tab_width = cmd.n_tabwidth[0]; else - handle->tab_width = 4; + tab_width = 4; break; case FH_IMAGE: - handle->mode = MODE_BINARY; + mode = MODE_BINARY; if (cmd.n_lrecl[0] == NOT_LONG) { msg (SE, _("Fixed-length records were specified on /RECFORM, but " "record length was not specified on /LRECL. " "Assuming 1024-character records.")); - handle->length = 1024; + length = 1024; } else if (cmd.n_lrecl[0] < 1) { msg (SE, _("Record length (%ld) must be at least one byte. " "1-character records will be assumed."), cmd.n_lrecl[0]); - handle->length = 1; + length = 1; } else - handle->length = cmd.n_lrecl[0]; + length = cmd.n_lrecl[0]; break; default: assert (0); } + handle = create_file_handle (handle_name, cmd.s_name, + mode, length, tab_width); + + return CMD_SUCCESS; lossage: free_file_handle (&cmd); return CMD_FAILURE; } - -/* File handle functions. */ - -/* Creates and returns a new file handle with the given values - and defaults for other values. Adds the created file handle - to the global list. */ -static struct file_handle * -create_file_handle (const char *handle_name, const char *filename) -{ - struct file_handle *handle; - - /* Create and initialize file handle. */ - handle = xmalloc (sizeof *handle); - handle->next = file_handles; - handle->name = xstrdup (handle_name); - handle->filename = xstrdup (filename); - handle->identity = fn_get_identity (filename); - handle->where.filename = handle->filename; - handle->where.line_number = 0; - handle->mode = MODE_TEXT; - handle->length = 1024; - handle->tab_width = 4; - handle->open_cnt = 0; - handle->type = NULL; - handle->aux = NULL; - file_handles = handle; - - return handle; -} - -static void -destroy_file_handle(void *fh_, void *aux UNUSED) -{ - struct file_handle *fh = fh_; - free (fh->name); - free (fh->filename); - fn_free_identity (fh->identity); - free (fh); -} - -static const char * -mode_name (const char *mode) -{ - assert (mode != NULL); - assert (mode[0] == 'r' || mode[0] == 'w'); - - return mode[0] == 'r' ? "reading" : "writing"; -} - - -/* Tries to open handle H with the given TYPE and MODE. - - TYPE is the sort of file, e.g. "system file". Only one given - type of access is allowed on a given file handle at once. - - MODE combines the read or write mode with the sharing mode. - The first character is 'r' for read, 'w' for write. The - second character is 's' to permit sharing, 'e' to require - exclusive access. - - Returns the address of a void * that the caller can use for - data specific to the file handle if successful, or a null - pointer on failure. For exclusive access modes the void * - will always be a null pointer at return. In shared access - modes the void * will necessarily be null only if no other - sharers are active. - - If successful, a reference to type is retained, so it should - probably be a string literal. */ -void ** -fh_open (struct file_handle *h, const char *type, const char *mode) -{ - assert (h != NULL); - assert (type != NULL); - assert (mode != NULL); - assert (mode[0] == 'r' || mode[0] == 'w'); - assert (mode[1] == 's' || mode[1] == 'e'); - assert (mode[2] == '\0'); - - if (h->open_cnt != 0) - { - if (strcmp (h->type, type)) - { - msg (SE, _("Can't open %s as a %s because it is " - "already open as a %s"), - handle_get_name (h), type, h->type); - return NULL; - } - else if (strcmp (h->open_mode, mode)) - { - msg (SE, _("Can't open %s as a %s for %s because it is " - "already open for %s"), - handle_get_name (h), type, - mode_name (mode), mode_name (h->open_mode)); - return NULL; - } - else if (h->open_mode[1] == 'e') - { - msg (SE, _("Can't re-open %s as a %s for %s"), - handle_get_name (h), type, mode_name (mode)); - return NULL; - } - } - else - { - h->type = type; - strcpy (h->open_mode, mode); - assert (h->aux == NULL); - } - h->open_cnt++; - - return &h->aux; -} -/* Closes file handle H, which must have been open for the - specified TYPE and MODE of access provided to fh_open(). - Returns zero if the file is now closed, nonzero if it is still - open due to another reference. */ -int -fh_close (struct file_handle *h, const char *type, const char *mode) -{ - assert (h != NULL); - assert (h->open_cnt > 0); - assert (type != NULL); - assert (!strcmp (type, h->type)); - assert (mode != NULL); - assert (!strcmp (mode, h->open_mode)); - - h->open_cnt--; - if (h->open_cnt == 0) - { - h->type = NULL; - h->aux = NULL; - } - return h->open_cnt; -} static struct linked_list *handle_list; @@ -354,7 +169,7 @@ fh_parse (void) char *filename = ds_c_str (&tokstr); char *handle_name = xmalloc (strlen (filename) + 3); sprintf (handle_name, "\"%s\"", filename); - handle = create_file_handle (handle_name, filename); + handle = create_file_handle_with_defaults (handle_name, filename); ll_push_front(handle_list, handle); free (handle_name); } @@ -365,52 +180,6 @@ fh_parse (void) return handle; } -/* Returns the identifier of file HANDLE. If HANDLE was created - by referring to a filename instead of a handle name, returns - the filename, enclosed in double quotes. Return value is - owned by the file handle. - - Useful for printing error messages about use of file handles. */ -const char * -handle_get_name (const struct file_handle *handle) -{ - assert (handle != NULL); - return handle->name; -} - -/* Returns the name of the file associated with HANDLE. */ -const char * -handle_get_filename (const struct file_handle *handle) -{ - assert (handle != NULL); - return handle->filename; -} - -/* Returns the mode of HANDLE. */ -enum file_handle_mode -handle_get_mode (const struct file_handle *handle) -{ - assert (handle != NULL); - return handle->mode; -} - -/* Returns the width of a logical record on HANDLE. */ -size_t -handle_get_record_width (const struct file_handle *handle) -{ - assert (handle != NULL); - return handle->length; -} - -/* Returns the number of characters per tab stop for HANDLE, or - zero if tabs are not to be expanded. Applicable only to - MODE_TEXT files. */ -size_t -handle_get_tab_width (const struct file_handle *handle) -{ - assert (handle != NULL); - return handle->tab_width; -} void diff --git a/tests/Makefile.am b/tests/Makefile.am index a80f9cd9..7f9d4677 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,6 +14,7 @@ TESTS = \ command/examine-extremes.sh \ command/examine-percentiles.sh \ command/file-label.sh \ + command/file-handle.sh \ command/filter.sh \ command/flip.sh \ command/import-export.sh \ diff --git a/tests/command/file-handle.sh b/tests/command/file-handle.sh new file mode 100755 index 00000000..fecb7b33 --- /dev/null +++ b/tests/command/file-handle.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +# This program's primary purpose is to test the FILE HANDLE command + +TEMPDIR=/tmp/pspp-tst-$$ +TESTFILE=$TEMPDIR/`basename $0`.sps + +here=`pwd`; + +# ensure that top_srcdir is absolute +cd $top_srcdir; top_srcdir=`pwd` + +STAT_CONFIG_PATH=$top_srcdir/config +export STAT_CONFIG_PATH + + +cleanup() +{ + cd / + rm -rf $TEMPDIR +} + + +fail() +{ + echo $activity + echo FAILED + cleanup; + exit 1; +} + + +no_result() +{ + echo $activity + echo NO RESULT; + cleanup; + exit 2; +} + +pass() +{ + cleanup; + exit 0; +} + +mkdir -p $TEMPDIR + +cd $TEMPDIR + +activity="create file" +cat > $TEMPDIR/wiggle.txt << EOF +1 +2 +5 +109 +EOF +if [ $? -ne 0 ] ; then no_result ; fi + + + +activity="create program" +cat > $TESTFILE << EOF +FILE HANDLE myhandle /NAME='$TEMPDIR/wiggle.txt'. +DATA LIST LIST FILE=myhandle /x *. +LIST. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + +activity="run program" +$SUPERVISOR $here/../src/pspp --testing-mode -o raw-ascii $TESTFILE +if [ $? -ne 0 ] ; then no_result ; fi + + +activity="compare output" +diff -b $TEMPDIR/pspp.list - << EOF +1.1 DATA LIST. Reading free-form data from file $TEMPDIR/wiggle.txt. ++--------+------+ +|Variable|Format| +#========#======# +|x |F8.0 | ++--------+------+ + + x +-------- + 1.00 + 2.00 + 5.00 + 109.00 + +EOF +if [ $? -ne 0 ] ; then fail ; fi + + +pass; -- 2.30.2