From: Ben Pfaff Date: Tue, 21 Feb 2023 19:05:16 +0000 (-0800) Subject: DISPLAY MACROS: New command. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3b06535f48bdb8c367d9738c5b379febecb65c12;p=pspp DISPLAY MACROS: New command. --- diff --git a/NEWS b/NEWS index 46973b48cf..79c0f000bf 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ Changes after 1.6.2: - Break variables are now optional. + * DISPLAY MACROS is now implemented. + * Removed the MODIFY VARS command, which is not in SPSS. * Building from a Git repository, which previously required GIMP, now diff --git a/src/language/command.def b/src/language/command.def index 5d642d693a..0131b5dc7d 100644 --- a/src/language/command.def +++ b/src/language/command.def @@ -19,6 +19,7 @@ DEF_CMD (S_ANY, F_ENHANCED, "CLOSE FILE HANDLE", cmd_close_file_handle) DEF_CMD (S_ANY, 0, "CACHE", cmd_cache) DEF_CMD (S_ANY, 0, "CD", cmd_cd) DEF_CMD (S_ANY, 0, "DEFINE", cmd_define) +DEF_CMD (S_ANY, 0, "DISPLAY MACROS", cmd_display_macros) DEF_CMD (S_ANY, 0, "DO REPEAT", cmd_do_repeat) DEF_CMD (S_ANY, 0, "END REPEAT", cmd_end_repeat) DEF_CMD (S_ANY, 0, "ECHO", cmd_echo) diff --git a/src/language/commands/sys-file-info.c b/src/language/commands/sys-file-info.c index c3ceefb699..1b2b678404 100644 --- a/src/language/commands/sys-file-info.c +++ b/src/language/commands/sys-file-info.c @@ -34,6 +34,7 @@ #include "language/command.h" #include "language/commands/file-handle.h" #include "language/lexer/lexer.h" +#include "language/lexer/macro.h" #include "language/lexer/variable-parser.h" #include "libpspp/array.h" #include "libpspp/hash-functions.h" @@ -271,23 +272,17 @@ error: /* DISPLAY utility. */ -static void display_macros (void); static void display_documents (const struct dictionary *dict); static void display_vectors (const struct dictionary *dict, int sorted); int cmd_display (struct lexer *lexer, struct dataset *ds) { - /* Whether to sort the list of variables alphabetically. */ - int sorted; - /* Variables to display. */ size_t n; const struct variable **vl; - if (lex_match_id (lexer, "MACROS")) - display_macros (); - else if (lex_match_id (lexer, "DOCUMENTS")) + if (lex_match_id (lexer, "DOCUMENTS")) display_documents (dataset_dict (ds)); else if (lex_match_id (lexer, "FILE")) { @@ -308,7 +303,7 @@ cmd_display (struct lexer *lexer, struct dataset *ds) { int flags; - sorted = lex_match_id (lexer, "SORTED"); + bool sorted = lex_match_id (lexer, "SORTED"); if (lex_match_id (lexer, "VECTORS")) { @@ -397,10 +392,67 @@ cmd_display (struct lexer *lexer, struct dataset *ds) return CMD_SUCCESS; } -static void -display_macros (void) +static int +compare_macros_by_name (const void *a_, const void *b_, const void *aux UNUSED) { - msg (SW, _("Macros not supported.")); + const struct macro *const *ap = a_; + const struct macro *const *bp = b_; + const struct macro *a = *ap; + const struct macro *b = *bp; + + return utf8_strcasecmp (a->name, b->name); +} + +int +cmd_display_macros (struct lexer *lexer, struct dataset *ds UNUSED) +{ + const struct macro_set *set = lex_get_macros (lexer); + + if (hmap_is_empty (&set->macros)) + { + msg (SN, _("No macros to display.")); + return CMD_SUCCESS; + } + + const struct macro **macros = xnmalloc (hmap_count (&set->macros), + sizeof *macros); + size_t n = 0; + const struct macro *m; + HMAP_FOR_EACH (m, struct macro, hmap_node, &set->macros) + macros[n++] = m; + assert (n == hmap_count (&set->macros)); + sort (macros, n, sizeof *macros, compare_macros_by_name, NULL); + + struct pivot_table *table = pivot_table_create (N_("Macros")); + + struct pivot_dimension *attributes = pivot_dimension_create ( + table, PIVOT_AXIS_COLUMN, N_("Attributes")); + pivot_category_create_leaf (attributes->root, + pivot_value_new_text (N_("Source Location"))); + + struct pivot_dimension *names = pivot_dimension_create ( + table, PIVOT_AXIS_ROW, N_("Name")); + names->root->show_label = true; + + for (size_t i = 0; i < n; i++) + { + const struct macro *m = macros[i]; + + pivot_category_create_leaf (names->root, + pivot_value_new_user_text (m->name, -1)); + + struct string location = DS_EMPTY_INITIALIZER; + msg_location_format (m->location, &location); + pivot_table_put2 ( + table, 0, i, + pivot_value_new_user_text_nocopy (ds_steal_cstr (&location))); + } + + pivot_table_submit (table); + + free (macros); + + return CMD_SUCCESS; } static char * diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 35a9afa381..d22985c7e5 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -362,6 +362,13 @@ lex_define_macro (struct lexer *lexer, struct macro *m) macro_set_add (lexer->macros, m); } +/* Returns LEXER's macro set. The caller should not modify it. */ +const struct macro_set * +lex_get_macros (const struct lexer *lexer) +{ + return lexer->macros; +} + /* Inserts READER into LEXER so that the next token read by LEXER comes from READER. Before the caller, LEXER must either be empty or at a T_ENDCMD token. */ diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index ae40a87a04..ccb8d73a80 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -97,6 +97,7 @@ void lex_destroy (struct lexer *); /* Macros. */ void lex_define_macro (struct lexer *, struct macro *); +const struct macro_set *lex_get_macros (const struct lexer *); /* Files. */ void lex_include (struct lexer *, struct lex_reader *); diff --git a/tests/language/commands/define.at b/tests/language/commands/define.at index fb66b01378..2e1a7eebad 100644 --- a/tests/language/commands/define.at +++ b/tests/language/commands/define.at @@ -2453,4 +2453,29 @@ AT_CHECK([pspp --testing-mode define.sps], [0], [dnl [[ < y > ]] ]) -AT_CLEANUP \ No newline at end of file +AT_CLEANUP + +AT_SETUP([DISPLAY MACROS]) +AT_DATA([define.sps], [dnl +DEFINE !b() 0 !ENDDEFINE. +DEFINE !macro() +a b c d +e f g h. +i j k l +1,2,3,4. +5+6+7. +m(n,o). +"a" "b" "c" 'a' 'b' 'c'. +"x "" y". +!ENDDEFINE. +DEFINE !a() 1 !ENDDEFINE. +DISPLAY MACROS. +]) +AT_CHECK([pspp -O format=csv define.sps], [0], [dnl +Table: Macros +Name,Source Location +!a,define.sps:12 +!b,define.sps:1 +!macro,define.sps:2-11 +]) +AT_CLEANUP