Completely rewrite src/data/format.[ch], to achieve better
[pspp-builds.git] / src / language / utilities / set.q
index 4a603de7ad7be23800874f679b20b0701bfbd9a6..25f09eb7d9d4d19392bb47ff345527bfdd762fe3 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
    Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 #include <data/settings.h>
 #include <data/variable.h>
 #include <language/command.h>
+#include <language/lexer/format-parser.h>
 #include <language/lexer/lexer.h>
 #include <language/line-buffer.h>
 #include <libpspp/alloc.h>
@@ -114,29 +115,28 @@ int tgetnum (const char *);
 
 /* (declarations) */
 
-/* (_functions) */
+/* (functions) */
 
-static bool do_cc (const char *cc_string, int idx);
+static bool do_cc (const char *cc_string, enum fmt_type);
 
 int
-cmd_set (void)
+cmd_set (struct dataset *ds)
 {
   struct cmd_set cmd;
-  bool ok = true;
 
-  if (!parse_set (&cmd, NULL))
+  if (!parse_set (ds, &cmd, NULL))
     return CMD_FAILURE;
 
   if (cmd.sbc_cca)
-    ok = ok && do_cc (cmd.s_cca, 0);
+    do_cc (cmd.s_cca, FMT_CCA);
   if (cmd.sbc_ccb)
-    ok = ok && do_cc (cmd.s_ccb, 1);
+    do_cc (cmd.s_ccb, FMT_CCB);
   if (cmd.sbc_ccc)
-    ok = ok && do_cc (cmd.s_ccc, 2);
+    do_cc (cmd.s_ccc, FMT_CCC);
   if (cmd.sbc_ccd)
-    ok = ok && do_cc (cmd.s_ccd, 3);
+    do_cc (cmd.s_ccd, FMT_CCD);
   if (cmd.sbc_cce)
-    ok = ok && do_cc (cmd.s_cce, 4);
+    do_cc (cmd.s_cce, FMT_CCE);
 
   if (cmd.sbc_prompt)
     getl_set_prompt (GETL_PROMPT_FIRST, cmd.s_prompt);
@@ -146,7 +146,7 @@ cmd_set (void)
     getl_set_prompt (GETL_PROMPT_DATA, cmd.s_dprompt);
 
   if (cmd.sbc_decimal)
-    set_decimal (cmd.dec == STC_DOT ? '.' : ',');
+    fmt_set_decimal (cmd.dec == STC_DOT ? '.' : ',');
   if (cmd.sbc_echo)
     set_echo (cmd.echo == STC_ON);
   if (cmd.sbc_endcmd)
@@ -202,13 +202,13 @@ cmd_set (void)
    grouping and decimal members appropriately.  Returns true if
    successful, false otherwise. */
 static bool
-find_cc_separators (const char *cc_string, struct custom_currency *cc)
+find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
 {
   const char *sp;
   int comma_cnt, dot_cnt;
   
   /* Count commas and periods.  There must be exactly three of
-     one or the other, except that an apostrophe acts escapes a
+     one or the other, except that an apostrophe escapes a
      following comma or period. */
   comma_cnt = dot_cnt = 0;
   for (sp = cc_string; *sp; sp++)
@@ -235,23 +235,23 @@ find_cc_separators (const char *cc_string, struct custom_currency *cc)
   return true;
 }
 
-/* Extracts a token from IN into TOKEn.  Tokens are delimited by
-   GROUPING.  The token is truncated to at most CC_WIDTH
-   characters (including null terminator).  Returns the first
-   character following the token. */
+/* Extracts a token from IN into a newly allocated AFFIX.  Tokens
+   are delimited by GROUPING.  The token is truncated to at most
+   FMT_STYLE_AFFIX_MAX characters.  Returns the first character
+   following the token. */
 static const char *
-extract_cc_token (const char *in, int grouping, char token[CC_WIDTH]
+extract_cc_token (const char *in, int grouping, struct substring *affix
 {
-  char *out = token;
-  
+  size_t ofs = 0;
+  ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX);
   for (; *in != '\0' && *in != grouping; in++) 
     {
       if (*in == '\'' && in[1] == grouping)
         in++;
-      if (out < &token[CC_WIDTH - 1])
-        *out++ = *in;
+      if (ofs < FMT_STYLE_AFFIX_MAX) 
+        ss_data (*affix)[ofs++] = *in;
     }
-  *out = '\0';
+  affix->length = ofs;
 
   if (*in == grouping)
     in++;
@@ -261,25 +261,26 @@ extract_cc_token (const char *in, int grouping, char token[CC_WIDTH])
 /* Sets custom currency specifier CC having name CC_NAME ('A' through
    'E') to correspond to the settings in CC_STRING. */
 static bool
-do_cc (const char *cc_string, int idx)
+do_cc (const char *cc_string, enum fmt_type type)
 {
-  struct custom_currency cc;
+  struct fmt_number_style *cc = fmt_number_style_create ();
   
   /* Determine separators. */
-  if (!find_cc_separators (cc_string, &cc)) 
+  if (!find_cc_separators (cc_string, cc)) 
     {
-      msg (SE, _("CC%c: Custom currency string `%s' does not contain "
-                 "exactly three periods or commas (not both)."),
-           "ABCDE"[idx], cc_string);
+      fmt_number_style_destroy (cc);
+      msg (SE, _("%s: Custom currency string `%s' does not contain "
+                 "exactly three periods or commas (or it contains both)."),
+           fmt_name (type), cc_string);
       return false;
     }
   
-  cc_string = extract_cc_token (cc_string, cc.grouping, cc.neg_prefix);
-  cc_string = extract_cc_token (cc_string, cc.grouping, cc.prefix);
-  cc_string = extract_cc_token (cc_string, cc.grouping, cc.suffix);
-  cc_string = extract_cc_token (cc_string, cc.grouping, cc.neg_suffix);
+  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix);
+  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix);
+  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix);
+  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix);
 
-  set_cc (idx, &cc);
+  fmt_set_style (type, cc);
   
   return true;
 }
@@ -288,7 +289,7 @@ do_cc (const char *cc_string, int idx)
    completely blank fields in numeric data imply.  X, Wnd: Syntax is
    SYSMIS or a numeric value. */
 static int
-stc_custom_blanks (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_blanks (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   lex_match ('=');
   if ((token == T_ID && lex_id_match ("SYSMIS", tokid)))
@@ -309,7 +310,7 @@ stc_custom_blanks (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 /* Parses the EPOCH subcommand, which controls the epoch used for
    parsing 2-digit years. */
 static int
-stc_custom_epoch (struct cmd_set *cmd UNUSED, void *aux UNUSED) 
+stc_custom_epoch (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED) 
 {
   lex_match ('=');
   if (lex_match_id ("AUTOMATIC"))
@@ -335,7 +336,7 @@ stc_custom_epoch (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 }
 
 static int
-stc_custom_length (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_length (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   int page_length;
 
@@ -362,7 +363,7 @@ stc_custom_length (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 }
 
 static int
-stc_custom_seed (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_seed (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   lex_match ('=');
   if (lex_match_id ("RANDOM"))
@@ -379,7 +380,7 @@ stc_custom_seed (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 }
 
 static int
-stc_custom_width (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_width (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   lex_match ('=');
   if (lex_match_id ("NARROW"))
@@ -405,18 +406,19 @@ stc_custom_width (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 /* Parses FORMAT subcommand, which consists of a numeric format
    specifier. */
 static int
-stc_custom_format (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_format (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   struct fmt_spec fmt;
 
   lex_match ('=');
-  if (!parse_format_specifier (&fmt, 0))
+  if (!parse_format_specifier (&fmt))
     return 0;
-  if ((formats[fmt.type].cat & FCAT_STRING) != 0)
+  if (fmt_is_string (fmt.type))
     {
+      char str[FMT_STRING_LEN_MAX + 1];
       msg (SE, _("FORMAT requires numeric output format as an argument.  "
                 "Specified format %s is of type string."),
-          fmt_to_string (&fmt));
+          fmt_to_string (&fmt, str));
       return 0;
     }
 
@@ -425,7 +427,7 @@ stc_custom_format (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 }
 
 static int
-stc_custom_journal (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_journal (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   lex_match ('=');
   if (!lex_match_id ("ON") && !lex_match_id ("OFF")) 
@@ -442,7 +444,7 @@ stc_custom_journal (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 }
 
 static int
-stc_custom_listing (struct cmd_set *cmd UNUSED, void *aux UNUSED)
+stc_custom_listing (struct dataset *ds UNUSED, struct cmd_set *cmd UNUSED, void *aux UNUSED)
 {
   bool listing;
 
@@ -462,13 +464,13 @@ stc_custom_listing (struct cmd_set *cmd UNUSED, void *aux UNUSED)
 }
 
 static int
-stc_custom_disk (struct cmd_set *cmd UNUSED, void *aux)
+stc_custom_disk (struct dataset *ds, struct cmd_set *cmd UNUSED, void *aux)
 {
-  return stc_custom_listing (cmd, aux);
+  return stc_custom_listing (ds, cmd, aux);
 }
 \f
 static void
-show_blanks (void
+show_blanks (const struct dataset *ds UNUSED
 {
   if (get_blanks () == SYSMIS)
     msg (SN, _("BLANKS is SYSMIS."));
@@ -478,22 +480,25 @@ show_blanks (void)
 }
 
 static char *
-format_cc (const char *in, char grouping, char *out) 
+format_cc (struct substring in, char grouping, char *out) 
 {
-  while (*in != '\0'
+  while (!ss_is_empty (in)
     {
-      if (*in == grouping || *in == '\'')
+      char c = ss_get_char (&in);
+      if (c == grouping || c == '\'')
         *out++ = '\'';
-      *out++ = *in++;
+      else if (c == '"')
+        *out++ = '"';
+      *out++ = c;
     }
   return out;
 }
 
 static void
-show_cc (int idx
+show_cc (enum fmt_type type
 {
-  const struct custom_currency *cc = get_cc (idx);
-  char cc_string[CC_WIDTH * 4 * 2 + 3 + 1];
+  const struct fmt_number_style *cc = fmt_get_style (type);
+  char cc_string[FMT_STYLE_AFFIX_MAX * 4 * 2 + 3 + 1];
   char *out;
 
   out = format_cc (cc->neg_prefix, cc->grouping, cc_string);
@@ -505,84 +510,84 @@ show_cc (int idx)
   out = format_cc (cc->neg_suffix, cc->grouping, out);
   *out = '\0';
   
-  msg (SN, _("CC%c is \"%s\"."), "ABCDE"[idx], cc_string);
+  msg (SN, _("%s is \"%s\"."), fmt_name (type), cc_string);
 }
 
-
 static void
-show_cca (void
+show_cca (const struct dataset *ds UNUSED
 {
-  show_cc (0);
+  show_cc (FMT_CCA);
 }
 
 static void
-show_ccb (void
+show_ccb (const struct dataset *ds UNUSED
 {
-  show_cc (1);
+  show_cc (FMT_CCB);
 }
 
 static void
-show_ccc (void
+show_ccc (const struct dataset *ds UNUSED
 {
-  show_cc (2);
+  show_cc (FMT_CCC);
 }
 
 static void
-show_ccd (void
+show_ccd (const struct dataset *ds UNUSED
 {
-  show_cc (3);
+  show_cc (FMT_CCD);
 }
 
 static void
-show_cce (void
+show_cce (const struct dataset *ds UNUSED
 {
-  show_cc (4);
+  show_cc (FMT_CCE);
 }
 
 static void
-show_decimals (void
+show_decimals (const struct dataset *ds UNUSED
 {
-  msg (SN, _("DECIMAL is \"%c\"."), get_decimal ());
+  msg (SN, _("DECIMAL is \"%c\"."), fmt_decimal_char (FMT_F));
 }
 
 static void
-show_endcmd (void
+show_endcmd (const struct dataset *ds UNUSED
 {
   msg (SN, _("ENDCMD is \"%c\"."), get_endcmd ());
 }
 
 static void
-show_format (void
+show_format (const struct dataset *ds UNUSED
 {
-  msg (SN, _("FORMAT is %s."), fmt_to_string (get_format ()));
+  char str[FMT_STRING_LEN_MAX + 1];
+  msg (SN, _("FORMAT is %s."), fmt_to_string (get_format (), str));
 }
 
 static void
-show_length (void
+show_length (const struct dataset *ds UNUSED
 {
   msg (SN, _("LENGTH is %d."), get_viewlength ());
 }
 
 static void
-show_mxerrs (void
+show_mxerrs (const struct dataset *ds UNUSED
 {
   msg (SN, _("MXERRS is %d."), get_mxerrs ());
 }
 
 static void
-show_mxloops (void
+show_mxloops (const struct dataset *ds UNUSED
 {
   msg (SN, _("MXLOOPS is %d."), get_mxloops ());
 }
 
 static void
-show_mxwarns (void
+show_mxwarns (const struct dataset *ds UNUSED
 {
   msg (SN, _("MXWARNS is %d."), get_mxwarns ());
 }
 
 static void
-show_scompression (void
+show_scompression (const struct dataset *ds UNUSED
 {
   if (get_scompression ())
     msg (SN, _("SCOMPRESSION is ON."));
@@ -591,7 +596,7 @@ show_scompression (void)
 }
 
 static void
-show_undefined (void
+show_undefined (const struct dataset *ds UNUSED
 {
   if (get_undefined ())
     msg (SN, _("UNDEFINED is WARN."));
@@ -600,9 +605,9 @@ show_undefined (void)
 }
 
 static void
-show_weight (void
+show_weight (const struct dataset *ds
 {
-  struct variable *var = dict_get_weight (default_dict);
+  struct variable *var = dict_get_weight (dataset_dict (ds));
   if (var == NULL)
     msg (SN, _("WEIGHT is off."));
   else
@@ -610,7 +615,7 @@ show_weight (void)
 }
 
 static void
-show_width (void
+show_width (const struct dataset *ds UNUSED
 {
   msg (SN, _("WIDTH is %d."), get_viewwidth ());
 }
@@ -618,10 +623,10 @@ show_width (void)
 struct show_sbc 
   {
     const char *name;
-    void (*function) (void);
+    void (*function) (const struct dataset *);
   };
 
-struct show_sbc show_table[] = 
+const struct show_sbc show_table[] = 
   {
     {"BLANKS", show_blanks},
     {"CCA", show_cca},
@@ -643,12 +648,12 @@ struct show_sbc show_table[] =
   };
 
 static void
-show_all (void
+show_all (const struct dataset *ds
 {
   size_t i;
   
   for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
-    show_table[i].function ();
+    show_table[i].function (ds);
 }
 
 static void
@@ -661,36 +666,36 @@ show_all_cc (void)
 }
 
 static void
-show_warranty (void
+show_warranty (const struct dataset *ds UNUSED
 {
   msg (MN, lack_of_warranty);
 }
 
 static void
-show_copying (void
+show_copying (const struct dataset *ds UNUSED
 {
   msg (MN, copyleft);
 }
 
 int
-cmd_show (void
+cmd_show (struct dataset *ds
 {
   if (token == '.') 
     {
-      show_all ();
+      show_all (ds);
       return CMD_SUCCESS;
     }
 
   do 
     {
       if (lex_match (T_ALL))
-        show_all ();
+        show_all (ds);
       else if (lex_match_id ("CC")) 
         show_all_cc ();
       else if (lex_match_id ("WARRANTY"))
-        show_warranty ();
+        show_warranty (ds);
       else if (lex_match_id ("COPYING"))
-        show_copying ();
+        show_copying (ds);
       else if (token == T_ID)
         {
           int i;
@@ -698,7 +703,7 @@ cmd_show (void)
           for (i = 0; i < sizeof show_table / sizeof *show_table; i++)
             if (lex_match_id (show_table[i].name)) 
               {
-                show_table[i].function ();
+                show_table[i].function (ds);
                 goto found;
               }
           lex_error (NULL);