1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
27 /* GNU C allows the programmer to declare that certain functions take
28 printf-like arguments, never return, etc. Conditionalize these
29 declarations on whether gcc is in use. */
31 #define ATTRIBUTE(X) __attribute__ (X)
36 /* Marks a function argument as possibly not used. */
37 #define UNUSED ATTRIBUTE ((unused))
39 /* Marks a function that will never return. */
40 #define NO_RETURN ATTRIBUTE ((noreturn))
42 /* Mark a function as taking a printf- or scanf-like format
43 string as its FMT'th argument and that the FIRST'th argument
44 is the first one to be checked against the format string. */
45 #define PRINTF_FORMAT(FMT, FIRST) ATTRIBUTE ((format (__printf__, FMT, FIRST)))
47 /* Max length of an input line. */
48 #define MAX_LINE_LEN 1024
50 /* Max token length. */
51 #define MAX_TOK_LEN 1024
54 static char *program_name;
56 /* Have the input and output files been opened yet? */
59 /* Input, output files. */
60 static FILE *in, *out;
62 /* Input, output file names. */
63 static char *ifn, *ofn;
65 /* Input, output file line number. */
66 static int ln, oln = 1;
68 /* Input line buffer, current position. */
69 static char *buf, *cp;
74 T_STRING = 256, /* String literal. */
75 T_ID = 257 /* Identifier. */
78 /* Current token: either one of the above, or a single character. */
81 /* Token string value. */
84 /* Utility functions. */
86 static char nullstr[] = "";
88 /* Close all open files and delete the output file, on failure. */
97 if (remove (ofn) == -1)
98 fprintf (stderr, "%s: %s: remove: %s\n", program_name, ofn, strerror (errno));
101 void hcf (void) NO_RETURN;
103 /* Terminate unsuccessfully. */
111 int fail (const char *, ...) PRINTF_FORMAT (1, 2);
112 int error (const char *, ...) PRINTF_FORMAT (1, 2);
114 /* Output an error message and terminate unsuccessfully. */
116 fail (const char *format, ...)
120 va_start (args, format);
121 fprintf (stderr, "%s: ", program_name);
122 vfprintf (stderr, format, args);
123 fprintf (stderr, "\n");
129 /* Output a context-dependent error message and terminate
132 error (const char *format,...)
136 va_start (args, format);
137 fprintf (stderr, "%s:%d: (column %d) ", ifn, ln, (int) (cp - buf));
138 vfprintf (stderr, format, args);
139 fprintf (stderr, "\n");
145 #define VME "virtual memory exhausted"
147 /* Allocate a block of SIZE bytes and return a pointer to its
150 xmalloc (size_t size)
159 fail ("xmalloc(%lu): %s", (unsigned long) size, VME);
164 /* Make a dynamically allocated copy of string S and return a pointer
165 to the first character. */
167 xstrdup (const char *s)
173 size = strlen (s) + 1;
177 fail ("xstrdup(%lu): %s", (unsigned long) strlen (s), VME);
183 /* Returns a pointer to one of 8 static buffers. The buffers are used
188 static char b[8][256];
197 /* Copies a string to a static buffer, converting it to lowercase in
198 the process, and returns a pointer to the static buffer. */
200 st_lower (const char *s)
204 p = cp = get_buffer ();
206 *cp++ = tolower ((unsigned char) (*s++));
212 /* Copies a string to a static buffer, converting it to uppercase in
213 the process, and returns a pointer to the static buffer. */
215 st_upper (const char *s)
219 p = cp = get_buffer ();
221 *cp++ = toupper ((unsigned char) (*s++));
227 /* Returns the address of the first non-whitespace character in S, or
228 the address of the null terminator if none. */
230 skip_ws (const char *s)
232 while (isspace ((unsigned char) *s))
237 /* Read one line from the input file into buf. Lines having special
238 formats are handled specially. */
243 if (0 == fgets (buf, MAX_LINE_LEN, in))
246 fail ("%s: fgets: %s", ifn, strerror (errno));
250 cp = strchr (buf, '\n');
258 /* Symbol table manager. */
260 /* Symbol table entry. */
261 typedef struct symbol symbol;
264 symbol *next; /* Next symbol in symbol table. */
265 char *name; /* Symbol name. */
266 int unique; /* 1=Name must be unique in this file. */
267 int ln; /* Line number of definition. */
268 int value; /* Symbol value. */
274 /* Add a symbol to the symbol table having name NAME, uniqueness
275 UNIQUE, and value VALUE. If a symbol having the same name is found
276 in the symbol table, its sequence number is returned and the symbol
277 table is not modified. Otherwise, the symbol is added and the next
278 available sequence number is returned. */
280 add_symbol (const char *name, int unique, int value)
285 sym = xmalloc (sizeof *sym);
286 sym->name = xstrdup (name);
287 sym->unique = unique;
300 if (!strcmp (iter->name, name))
304 fprintf (stderr, "%s:%d: `%s' is already defined above\n", ifn,
306 fprintf (stderr, "%s:%d: location of previous definition\n", ifn,
323 /* Finds the symbol having given sequence number X within the symbol
324 table, and returns the associated symbol structure. */
331 while (x > 1 && iter)
341 /* Writes a printable representation of the current token to
349 printf ("STRING\t\"%s\"\n", tokstr);
352 printf ("ID\t%s\n", tokstr);
355 printf ("PUNCT\t%c\n", token);
358 #endif /* DUMP_TOKENS */
360 /* Reads a token from the input file. */
364 /* Skip whitespace and check for end of file. */
372 fail ("%s: Unexpected end of file.", ifn);
380 while (*cp != '"' && *cp)
386 error ("Unterminated string literal.");
394 error ("Unterminated string literal.");
397 else if (*cp == '_' || isalnum ((unsigned char) *cp))
401 while (*cp == '_' || isalnum ((unsigned char) *cp))
402 *dest++ = toupper ((unsigned char) (*cp++));
415 /* Force the current token to be an identifier token. */
420 error ("Identifier expected.");
423 /* Force the current token to be a string token. */
427 if (token != T_STRING)
428 error ("String expected.");
431 /* Checks whether the current token is the identifier S; if so, skips
432 the token and returns true; otherwise, returns false. */
434 match_id (const char *s)
436 if (token == T_ID && !strcmp (tokstr, s))
444 /* Checks whether the current token is T. If so, skips the token and
445 returns true; otherwise, returns false. */
457 /* Force the current token to be T, and skip it. */
462 error ("`%c' expected.", t);
468 /* Some specifiers have associated values. */
471 VAL_NONE, /* No value. */
472 VAL_INT, /* Integer value. */
473 VAL_DBL, /* Floating point value. */
474 VAL_STRING /* String value. */
477 /* For those specifiers with values, the syntax of those values. */
480 VT_PLAIN, /* Unadorned value. */
481 VT_PAREN /* Value must be enclosed in parentheses. */
484 /* Forward definition. */
485 typedef struct specifier specifier;
487 /* A single setting. */
488 typedef struct setting setting;
491 specifier *parent; /* Owning specifier. */
492 setting *next; /* Next in the chain. */
493 char *specname; /* Name of the setting. */
494 int con; /* Sequence number. */
497 int valtype; /* One of VT_*. */
498 int value; /* One of VAL_*. */
499 int optvalue; /* 1=value is optional, 0=value is required. */
500 char *valname; /* Variable name for the value. */
501 char *restriction; /* !=NULL: expression specifying valid values. */
504 /* A single specifier. */
507 specifier *next; /* Next in the chain. */
508 char *varname; /* Variable name. */
509 setting *s; /* Associated settings. */
511 setting *def; /* Default setting. */
512 setting *omit_kw; /* Setting for which the keyword can be omitted. */
514 int index; /* Next array index. */
517 /* Subcommand types. */
520 SBC_PLAIN, /* The usual case. */
521 SBC_VARLIST, /* Variable list. */
522 SBC_INT, /* Integer value. */
523 SBC_PINT, /* Integer inside parentheses. */
524 SBC_DBL, /* Floating point value. */
525 SBC_INT_LIST, /* List of integers (?). */
526 SBC_DBL_LIST, /* List of floating points (?). */
527 SBC_CUSTOM, /* Custom. */
528 SBC_ARRAY, /* Array of boolean values. */
529 SBC_STRING, /* String value. */
530 SBC_VAR /* Single variable name. */
536 ARITY_ONCE_EXACTLY, /* must occur exactly once */
537 ARITY_ONCE_ONLY, /* zero or once */
538 ARITY_MANY /* 0, 1, ... , inf */
541 /* A single subcommand. */
542 typedef struct subcommand subcommand;
545 subcommand *next; /* Next in the chain. */
546 char *name; /* Subcommand name. */
547 subcommand_type type; /* One of SBC_*. */
548 subcommand_arity arity; /* How many times should the subcommand occur*/
549 int narray; /* Index of next array element. */
550 const char *prefix; /* Prefix for variable and constant names. */
551 specifier *spec; /* Array of specifiers. */
553 /* SBC_STRING and SBC_INT only. */
554 char *restriction; /* Expression restricting string length. */
555 char *message; /* Error message. */
556 int translatable; /* Error message is translatable */
559 /* Name of the command; i.e., DESCRIPTIVES. */
562 /* Short prefix for the command; i.e., `dsc_'. */
565 /* List of subcommands. */
566 subcommand *subcommands;
568 /* Default subcommand if any, or NULL. */
573 void parse_subcommands (void);
575 /* Parse an entire specification. */
579 /* Get the command name and prefix. */
580 if (token != T_STRING && token != T_ID)
581 error ("Command name expected.");
582 cmdname = xstrdup (tokstr);
586 prefix = xstrdup (tokstr);
591 /* Read all the subcommands. */
594 parse_subcommands ();
597 /* Parses a single setting into S, given subcommand information SBC
598 and specifier information SPEC. */
600 parse_setting (setting *s, specifier *spec)
604 if (match_token ('*'))
607 error ("Cannot have two settings with omittable keywords.");
612 if (match_token ('!'))
615 error ("Cannot have two default settings.");
621 s->specname = xstrdup (tokstr);
622 s->con = add_symbol (s->specname, 0, 0);
627 /* Parse setting value info if necessary. */
628 if (token != '/' && token != ';' && token != '.' && token != ',')
632 s->valtype = VT_PAREN;
636 s->valtype = VT_PLAIN;
638 s->optvalue = match_token ('*');
642 else if (match_id ("D"))
644 else if (match_id ("S"))
645 s->value = VAL_STRING;
647 error ("`n', `d', or `s' expected.");
652 s->valname = xstrdup (tokstr);
659 s->restriction = xstrdup (tokstr);
663 s->restriction = NULL;
665 if (s->valtype == VT_PAREN)
670 /* Parse a single specifier into SPEC, given subcommand information
673 parse_specifier (specifier *spec, subcommand *sbc)
678 spec->omit_kw = NULL;
679 spec->varname = NULL;
683 spec->varname = xstrdup (st_lower (tokstr));
687 /* Handle array elements. */
690 spec->index = sbc->narray;
691 if (sbc->type == SBC_ARRAY)
703 if ( sbc->type == SBC_ARRAY && token == T_ID )
705 spec->varname = xstrdup (st_lower (tokstr));
706 spec->index = sbc->narray;
712 /* Parse all the settings. */
714 setting **s = &spec->s;
718 *s = xmalloc (sizeof **s);
719 parse_setting (*s, spec);
720 if (token == ',' || token == ';' || token == '.')
729 /* Parse a list of specifiers for subcommand SBC. */
731 parse_specifiers (subcommand *sbc)
733 specifier **spec = &sbc->spec;
735 if (token == ';' || token == '.')
743 *spec = xmalloc (sizeof **spec);
744 parse_specifier (*spec, sbc);
745 if (token == ';' || token == '.')
748 spec = &(*spec)->next;
750 (*spec)->next = NULL;
753 /* Parse a subcommand into SBC. */
755 parse_subcommand (subcommand *sbc)
757 if (match_token ('*'))
760 error ("Multiple default subcommands.");
764 sbc->arity = ARITY_ONCE_ONLY;
765 if ( match_token('+'))
766 sbc->arity = ARITY_MANY;
767 else if (match_token('^'))
768 sbc->arity = ARITY_ONCE_EXACTLY ;
772 sbc->name = xstrdup (tokstr);
776 sbc->type = SBC_PLAIN;
778 sbc->translatable = 0;
780 if (match_token ('['))
783 sbc->prefix = xstrdup (st_lower (tokstr));
789 sbc->type = SBC_ARRAY;
790 parse_specifiers (sbc);
795 if (match_token ('('))
798 sbc->prefix = xstrdup (st_lower (tokstr));
808 if (match_id ("VAR"))
810 if (match_id ("VARLIST"))
812 if (match_token ('('))
815 sbc->message = xstrdup (tokstr);
820 else sbc->message = NULL;
822 sbc->type = SBC_VARLIST;
824 else if (match_id ("INTEGER"))
826 sbc->type = match_id ("LIST") ? SBC_INT_LIST : SBC_INT;
827 if ( token == T_STRING)
829 sbc->restriction = xstrdup (tokstr);
831 if ( match_id("N_") )
837 sbc->translatable = 1;
843 sbc->message = xstrdup (tokstr);
846 sbc->restriction = NULL;
848 else if (match_id ("PINT"))
849 sbc->type = SBC_PINT;
850 else if (match_id ("DOUBLE"))
852 if ( match_id ("LIST") )
853 sbc->type = SBC_DBL_LIST;
857 else if (match_id ("STRING"))
859 sbc->type = SBC_STRING;
860 if (token == T_STRING)
862 sbc->restriction = xstrdup (tokstr);
865 sbc->message = xstrdup (tokstr);
869 sbc->restriction = NULL;
871 else if (match_id ("CUSTOM"))
872 sbc->type = SBC_CUSTOM;
874 parse_specifiers (sbc);
878 /* Parse all the subcommands. */
880 parse_subcommands (void)
882 subcommand **sbc = &subcommands;
886 *sbc = xmalloc (sizeof **sbc);
889 parse_subcommand (*sbc);
901 #define BASE_INDENT 2 /* Starting indent. */
902 #define INC_INDENT 2 /* Indent increment. */
904 /* Increment the indent. */
905 #define indent() indent += INC_INDENT
906 #define outdent() indent -= INC_INDENT
908 /* Size of the indent from the left margin. */
911 void dump (int, const char *, ...) PRINTF_FORMAT (2, 3);
913 /* Write line FORMAT to the output file, formatted as with printf,
914 indented `indent' characters from the left margin. If INDENTION is
915 greater than 0, indents BASE_INDENT * INDENTION characters after
916 writing the line; if INDENTION is less than 0, dedents BASE_INDENT
917 * INDENTION characters _before_ writing the line. */
919 dump (int indention, const char *format, ...)
925 indent += BASE_INDENT * indention;
928 va_start (args, format);
929 for (i = 0; i < indent; i++)
931 vfprintf (out, format, args);
936 indent += BASE_INDENT * indention;
939 /* Write the structure members for specifier SPEC to the output file.
940 SBC is the including subcommand. */
942 dump_specifier_vars (const specifier *spec, const subcommand *sbc)
945 dump (0, "long %s%s;", sbc->prefix, spec->varname);
950 for (s = spec->s; s; s = s->next)
952 if (s->value != VAL_NONE)
954 const char *typename;
956 assert (s->value == VAL_INT || s->value == VAL_DBL
957 || s->value == VAL_STRING);
958 typename = (s->value == VAL_INT ? "long"
959 : s->value == VAL_DBL ? "double"
962 dump (0, "%s %s%s;", typename, sbc->prefix, st_lower (s->valname));
968 /* Returns true if string T is a PSPP keyword, false otherwise. */
970 is_keyword (const char *t)
972 static const char *kw[] =
974 "AND", "OR", "NOT", "EQ", "GE", "GT", "LE", "LT",
975 "NE", "ALL", "BY", "TO", "WITH", 0,
979 for (cp = kw; *cp; cp++)
980 if (!strcmp (t, *cp))
985 /* Transforms a string NAME into a valid C identifier: makes
986 everything lowercase and maps nonalphabetic characters to
987 underscores. Returns a pointer to a static buffer. */
989 make_identifier (const char *name)
991 char *p = get_buffer ();
994 for (cp = p; *name; name++)
995 if (isalpha ((unsigned char) *name))
996 *cp++ = tolower ((unsigned char) (*name));
1004 /* Writes the struct and enum declarations for the parser. */
1006 dump_declarations (void)
1010 dump (0, "struct dataset;");
1012 /* Write out enums for all the identifiers in the symbol table. */
1018 /* Note the squirmings necessary to make sure that the last enum
1019 is not followed by a comma, as mandated by ANSI C89. */
1020 for (sym = symtab, f = k = 0; sym; sym = sym->next)
1021 if (!sym->unique && !is_keyword (sym->name))
1025 dump (0, "/* Settings for subcommand specifiers. */");
1032 buf = xmalloc (1024);
1037 sprintf (buf, "%s%s,", st_upper (prefix), sym->name);
1041 sprintf (buf, "%s%s = 1000,", st_upper (prefix), sym->name);
1046 buf[strlen (buf) - 1] = 0;
1057 /* Write out some type definitions */
1059 dump (0, "#define MAXLISTS 10");
1063 /* For every array subcommand, write out the associated enumerated
1068 for (sbc = subcommands; sbc; sbc = sbc->next)
1069 if (sbc->type == SBC_ARRAY && sbc->narray)
1071 dump (0, "/* Array indices for %s subcommand. */", sbc->name);
1079 for (spec = sbc->spec; spec; spec = spec->next)
1080 dump (0, "%s%s%s = %d,",
1081 st_upper (prefix), st_upper (sbc->prefix),
1082 st_upper (spec->varname), spec->index);
1084 dump (0, "%s%scount", st_upper (prefix), st_upper (sbc->prefix));
1092 /* Write out structure declaration. */
1096 dump (0, "/* %s structure. */", cmdname);
1097 dump (1, "struct cmd_%s", make_identifier (cmdname));
1099 for (sbc = subcommands; sbc; sbc = sbc->next)
1103 if (sbc != subcommands)
1106 dump (0, "/* %s subcommand. */", sbc->name);
1107 dump (0, "int sbc_%s;", st_lower (sbc->name));
1116 for (spec = sbc->spec; spec; spec = spec->next)
1120 if (sbc->type == SBC_PLAIN)
1121 dump (0, "long int %s%s;", st_lower (sbc->prefix),
1125 dump (0, "int a_%s[%s%scount];",
1126 st_lower (sbc->name),
1128 st_upper (sbc->prefix)
1135 dump_specifier_vars (spec, sbc);
1141 dump (0, "size_t %sn_%s;", st_lower (sbc->prefix),
1142 st_lower (sbc->name));
1143 dump (0, "const struct variable **%sv_%s;", st_lower (sbc->prefix),
1144 st_lower (sbc->name));
1148 dump (0, "const struct variable *%sv_%s;", st_lower (sbc->prefix),
1149 st_lower (sbc->name));
1153 dump (0, "char *s_%s;", st_lower (sbc->name));
1158 dump (0, "long n_%s[MAXLISTS];", st_lower (sbc->name));
1162 dump (0, "double n_%s[MAXLISTS];", st_lower (sbc->name));
1166 dump (0, "subc_list_double dl_%s[MAXLISTS];",
1167 st_lower(sbc->name));
1171 dump (0, "subc_list_int il_%s[MAXLISTS];",
1172 st_lower(sbc->name));
1185 /* Write out prototypes for custom_*() functions as necessary. */
1190 for (sbc = subcommands; sbc; sbc = sbc->next)
1191 if (sbc->type == SBC_CUSTOM)
1196 dump (0, "/* Prototype for custom subcommands of %s. */",
1199 dump (0, "static int %scustom_%s (struct lexer *, struct dataset *, struct cmd_%s *, void *);",
1200 st_lower (prefix), st_lower (sbc->name),
1201 make_identifier (cmdname));
1208 /* Prototypes for parsing and freeing functions. */
1210 dump (0, "/* Command parsing functions. */");
1211 dump (0, "static int parse_%s (struct lexer *, struct dataset *, struct cmd_%s *, void *);",
1212 make_identifier (cmdname), make_identifier (cmdname));
1213 dump (0, "static void free_%s (struct cmd_%s *);",
1214 make_identifier (cmdname), make_identifier (cmdname));
1219 /* Writes out code to initialize all the variables that need
1220 initialization for particular specifier SPEC inside subcommand SBC. */
1222 dump_specifier_init (const specifier *spec, const subcommand *sbc)
1230 st_upper (prefix), find_symbol (spec->def->con)->name);
1233 dump (0, "p->%s%s = %s;", sbc->prefix, spec->varname, s);
1239 for (s = spec->s; s; s = s->next)
1241 if (s->value != VAL_NONE)
1245 assert (s->value == VAL_INT || s->value == VAL_DBL
1246 || s->value == VAL_STRING);
1247 init = (s->value == VAL_INT ? "LONG_MIN"
1248 : s->value == VAL_DBL ? "SYSMIS"
1251 dump (0, "p->%s%s = %s;", sbc->prefix, st_lower (s->valname), init);
1257 /* Write code to initialize all variables. */
1259 dump_vars_init (int persistent)
1261 /* Loop through all the subcommands. */
1265 for (sbc = subcommands; sbc; sbc = sbc->next)
1269 dump (0, "p->sbc_%s = 0;", st_lower (sbc->name));
1278 dump (1, "for (i = 0; i < MAXLISTS; ++i)");
1279 dump (0, "subc_list_%s_create(&p->%cl_%s[i]) ;",
1280 sbc->type == SBC_INT_LIST ? "int" : "double",
1281 sbc->type == SBC_INT_LIST ? 'i' : 'd',
1282 st_lower (sbc->name)
1290 dump (1, "for (i = 0; i < MAXLISTS; ++i)");
1291 dump (0, "p->n_%s[i] = SYSMIS;", st_lower (sbc->name));
1304 for (spec = sbc->spec; spec; spec = spec->next)
1305 if (spec->s == NULL)
1307 if (sbc->type == SBC_PLAIN)
1308 dump (0, "p->%s%s = 0;", sbc->prefix, spec->varname);
1311 dump (0, "memset (p->a_%s, 0, sizeof p->a_%s);",
1312 st_lower (sbc->name), st_lower (sbc->name));
1317 dump_specifier_init (spec, sbc);
1322 dump (0, "p->%sn_%s = 0;",
1323 st_lower (sbc->prefix), st_lower (sbc->name));
1324 dump (0, "p->%sv_%s = NULL;",
1325 st_lower (sbc->prefix), st_lower (sbc->name));
1329 dump (0, "p->%sv_%s = NULL;",
1330 st_lower (sbc->prefix), st_lower (sbc->name));
1334 dump (0, "p->s_%s = NULL;", st_lower (sbc->name));
1341 dump (1, "for (i = 0; i < MAXLISTS; ++i)");
1342 dump (0, "p->n_%s[i] = LONG_MIN;", st_lower (sbc->name));
1354 /* Return a pointer to a static buffer containing an expression that
1355 will match token T. */
1357 make_match (const char *t)
1367 sprintf (s, "lex_match (lexer, T_%s)", t);
1368 else if (!strcmp (t, "ON") || !strcmp (t, "YES"))
1369 strcpy (s, "(lex_match_id (lexer, \"ON\") || lex_match_id (lexer, \"YES\") "
1370 "|| lex_match_id (lexer, \"TRUE\"))");
1371 else if (!strcmp (t, "OFF") || !strcmp (t, "NO"))
1372 strcpy (s, "(lex_match_id (lexer, \"OFF\") || lex_match_id (lexer, \"NO\") "
1373 "|| lex_match_id (lexer, \"FALSE\"))");
1374 else if (isdigit ((unsigned char) t[0]))
1375 sprintf (s, "lex_match_int (lexer, %s)", t);
1377 sprintf (s, "lex_match_id (lexer, \"%s\")", t);
1382 /* Write out the parsing code for specifier SPEC within subcommand
1385 dump_specifier_parse (const specifier *spec, const subcommand *sbc)
1389 if (spec->omit_kw && spec->omit_kw->next)
1390 error ("Omittable setting is not last setting in `%s' specifier.",
1392 if (spec->omit_kw && spec->omit_kw->parent->next)
1393 error ("Default specifier is not in last specifier in `%s' "
1394 "subcommand.", sbc->name);
1396 for (s = spec->s; s; s = s->next)
1398 int first = spec == sbc->spec && s == spec->s;
1400 /* Match the setting's keyword. */
1401 if (spec->omit_kw == s)
1408 dump (1, "%s;", make_match (s->specname));
1411 dump (1, "%sif (%s)", first ? "" : "else ",
1412 make_match (s->specname));
1415 /* Handle values. */
1416 if (s->value == VAL_NONE)
1417 dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname,
1418 st_upper (prefix), find_symbol (s->con)->name);
1421 if (spec->omit_kw != s)
1426 dump (0, "p->%s%s = %s%s;", sbc->prefix, spec->varname,
1427 st_upper (prefix), find_symbol (s->con)->name);
1429 if ( sbc->type == SBC_ARRAY )
1430 dump (0, "p->a_%s[%s%s%s] = 1;",
1431 st_lower (sbc->name),
1432 st_upper (prefix), st_upper (sbc->prefix),
1433 st_upper (spec->varname));
1437 if (s->valtype == VT_PAREN)
1441 dump (1, "if (lex_match (lexer, '('))");
1446 dump (1, "if (!lex_match (lexer, '('))");
1448 dump (0, "msg (SE, _(\"`(' expected after %s "
1449 "specifier of %s subcommand.\"));",
1450 s->specname, sbc->name);
1451 dump (0, "goto lossage;");
1457 if (s->value == VAL_INT)
1459 dump (1, "if (!lex_is_integer (lexer))");
1461 dump (0, "msg (SE, _(\"%s specifier of %s subcommand "
1462 "requires an integer argument.\"));",
1463 s->specname, sbc->name);
1464 dump (0, "goto lossage;");
1466 dump (-1, "p->%s%s = lex_integer (lexer);",
1467 sbc->prefix, st_lower (s->valname));
1469 else if (s->value == VAL_DBL)
1471 dump (1, "if (!lex_is_number (lexer))");
1473 dump (0, "msg (SE, _(\"Number expected after %s "
1474 "specifier of %s subcommand.\"));",
1475 s->specname, sbc->name);
1476 dump (0, "goto lossage;");
1478 dump (-1, "p->%s%s = lex_tokval (lexer);", sbc->prefix,
1479 st_lower (s->valname));
1481 else if (s->value == VAL_STRING)
1483 dump (1, "if (lex_token (lexer) != T_ID "
1484 "&& lex_token (lexer) != T_STRING)");
1486 dump (0, "msg (SE, _(\"%s specifier of %s subcommand "
1487 "requires a string argument.\"));",
1488 s->specname, sbc->name);
1489 dump (0, "goto lossage;");
1491 dump (-1, "free (p->%s%s);", sbc->prefix, st_lower (s->valname));
1492 dump (0, "p->%s%s = xstrdup (ds_cstr (lex_tokstr (lexer)));",
1493 sbc->prefix, st_lower (s->valname));
1502 str = xmalloc (MAX_TOK_LEN);
1503 str2 = xmalloc (MAX_TOK_LEN);
1504 sprintf (str2, "p->%s%s", sbc->prefix, st_lower (s->valname));
1505 sprintf (str, s->restriction, str2, str2, str2, str2,
1506 str2, str2, str2, str2);
1507 dump (1, "if (!(%s))", str);
1513 dump (0, "msg (SE, _(\"Bad argument for %s "
1514 "specifier of %s subcommand.\"));",
1515 s->specname, sbc->name);
1516 dump (0, "goto lossage;");
1521 dump (0, "lex_get (lexer);");
1523 if (s->valtype == VT_PAREN)
1525 dump (1, "if (!lex_match (lexer, ')'))");
1527 dump (0, "msg (SE, _(\"`)' expected after argument for "
1528 "%s specifier of %s.\"));",
1529 s->specname, sbc->name);
1530 dump (0, "goto lossage;");
1540 if (s != spec->omit_kw)
1544 if (s == spec->omit_kw)
1553 /* Write out the code to parse subcommand SBC. */
1555 dump_subcommand (const subcommand *sbc)
1557 if (sbc->type == SBC_PLAIN || sbc->type == SBC_ARRAY)
1561 dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')");
1567 for (count = 0, spec = sbc->spec; spec; spec = spec->next)
1570 dump_specifier_parse (spec, sbc);
1574 dump (1, "%sif (%s)", spec != sbc->spec ? "else " : "",
1575 make_match (st_upper (spec->varname)));
1576 if (sbc->type == SBC_PLAIN)
1577 dump (0, "p->%s%s = 1;", st_lower (sbc->prefix),
1580 dump (0, "p->a_%s[%s%s%s] = 1;",
1581 st_lower (sbc->name),
1582 st_upper (prefix), st_upper (sbc->prefix),
1583 st_upper (spec->varname));
1593 /* This code first finds the last specifier in sbc. Then it
1594 finds the last setting within that last specifier. Either
1595 or both might be NULL. */
1608 if (spec && (!spec->s || !spec->omit_kw))
1612 dump (0, "lex_error (lexer, NULL);");
1613 dump (0, "goto lossage;");
1619 dump (0, "lex_match (lexer, ',');");
1623 else if (sbc->type == SBC_VARLIST)
1625 dump (1, "if (!parse_variables_const (lexer, dataset_dict (ds), &p->%sv_%s, &p->%sn_%s, "
1627 st_lower (sbc->prefix), st_lower (sbc->name),
1628 st_lower (sbc->prefix), st_lower (sbc->name),
1629 sbc->message ? " |" : "",
1630 sbc->message ? sbc->message : "");
1631 dump (0, "goto lossage;");
1634 else if (sbc->type == SBC_VAR)
1636 dump (0, "p->%sv_%s = parse_variable (lexer, dataset_dict (ds));",
1637 st_lower (sbc->prefix), st_lower (sbc->name));
1638 dump (1, "if (!p->%sv_%s)",
1639 st_lower (sbc->prefix), st_lower (sbc->name));
1640 dump (0, "goto lossage;");
1643 else if (sbc->type == SBC_STRING)
1645 if (sbc->restriction)
1650 dump (1, "if (!lex_force_string (lexer))");
1651 dump (0, "return false;");
1653 if (sbc->restriction)
1655 dump (0, "x = ds_length (lex_tokstr (lexer));");
1656 dump (1, "if (!(%s))", sbc->restriction);
1658 dump (0, "msg (SE, _(\"String for %s must be %s.\"));",
1659 sbc->name, sbc->message);
1660 dump (0, "goto lossage;");
1664 dump (0, "free(p->s_%s);", st_lower(sbc->name) );
1665 dump (0, "p->s_%s = ds_xstrdup (lex_tokstr (lexer));",
1666 st_lower (sbc->name));
1667 dump (0, "lex_get (lexer);");
1668 if (sbc->restriction)
1671 else if (sbc->type == SBC_DBL)
1673 dump (1, "if (!lex_force_num (lexer))");
1674 dump (0, "goto lossage;");
1675 dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number (lexer);",
1676 st_lower (sbc->name), st_lower (sbc->name) );
1677 dump (0, "lex_get(lexer);");
1679 else if (sbc->type == SBC_INT)
1683 dump (1, "if (!lex_force_int (lexer))");
1684 dump (0, "goto lossage;");
1685 dump (-1, "x = lex_integer (lexer);");
1686 dump (0, "lex_get(lexer);");
1687 if (sbc->restriction)
1690 dump (1, "if (!(%s))", sbc->restriction);
1692 sprintf(buf,sbc->message,sbc->name);
1693 if ( sbc->translatable )
1694 dump (0, "msg (SE, gettext(\"%s\"));",buf);
1696 dump (0, "msg (SE, \"%s\");",buf);
1697 dump (0, "goto lossage;");
1700 dump (0, "p->n_%s[p->sbc_%s - 1] = x;", st_lower (sbc->name), st_lower(sbc->name) );
1703 else if (sbc->type == SBC_PINT)
1705 dump (0, "lex_match (lexer, '(');");
1706 dump (1, "if (!lex_force_int (lexer))");
1707 dump (0, "goto lossage;");
1708 dump (-1, "p->n_%s = lex_integer (lexer);", st_lower (sbc->name));
1709 dump (0, "lex_match (lexer, ')');");
1711 else if (sbc->type == SBC_DBL_LIST || sbc->type == SBC_INT_LIST)
1713 dump (0, "if ( p->sbc_%s > MAXLISTS)",st_lower(sbc->name));
1715 dump (0, "msg (SE, \"No more than %%d %s subcommands allowed\",MAXLISTS);",st_lower(sbc->name));
1716 dump (0, "goto lossage;");
1719 dump (1, "while (lex_token (lexer) != '/' && lex_token (lexer) != '.')");
1721 dump (0, "lex_match (lexer, ',');");
1722 dump (0, "if (!lex_force_num (lexer))");
1724 dump (0, "goto lossage;");
1727 dump (0, "subc_list_%s_push (&p->%cl_%s[p->sbc_%s-1], lex_number (lexer));",
1728 sbc->type == SBC_INT_LIST ? "int" : "double",
1729 sbc->type == SBC_INT_LIST ? 'i' : 'd',
1730 st_lower (sbc->name), st_lower (sbc->name));
1732 dump (0, "lex_get (lexer);");
1736 else if (sbc->type == SBC_CUSTOM)
1738 dump (1, "switch (%scustom_%s (lexer, ds, p, aux))",
1739 st_lower (prefix), st_lower (sbc->name));
1741 dump (1, "case 0:");
1742 dump (0, "goto lossage;");
1743 dump (-1, "case 1:");
1746 dump (-1, "case 2:");
1748 dump (0, "lex_error (lexer, NULL);");
1749 dump (0, "goto lossage;");
1750 dump (-1, "default:");
1752 dump (0, "NOT_REACHED ();");
1758 /* Write out entire parser. */
1760 dump_parser (int persistent)
1766 dump (0, "static int");
1767 dump (0, "parse_%s (struct lexer *lexer, struct dataset *ds%s, struct cmd_%s *p, void *aux UNUSED)",
1768 make_identifier (cmdname),
1769 (def && ( def->type == SBC_VARLIST && def->type == SBC_CUSTOM))?"":" UNUSED",
1770 make_identifier (cmdname));
1773 dump_vars_init (persistent);
1775 dump (1, "for (;;)");
1779 if (def && (def->type == SBC_VARLIST))
1781 if (def->type == SBC_VARLIST)
1782 dump (1, "if (lex_token (lexer) == T_ID "
1783 "&& dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) != NULL "
1784 "&& lex_look_ahead (lexer) != '=')");
1787 dump (0, "if ((lex_token (lexer) == T_ID "
1788 "&& dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) "
1789 "&& lex_look_ahead () != '=')");
1790 dump (1, " || token == T_ALL)");
1793 dump (0, "p->sbc_%s++;", st_lower (def->name));
1794 dump (1, "if (!parse_variables_const (lexer, dataset_dict (ds), &p->%sv_%s, &p->%sn_%s, "
1796 st_lower (def->prefix), st_lower (def->name),
1797 st_lower (def->prefix), st_lower (def->name));
1798 dump (0, "goto lossage;");
1803 else if (def && def->type == SBC_CUSTOM)
1805 dump (1, "switch (%scustom_%s (lexer, ds, p, aux))",
1806 st_lower (prefix), st_lower (def->name));
1808 dump (1, "case 0:");
1809 dump (0, "goto lossage;");
1810 dump (-1, "case 1:");
1812 dump (0, "p->sbc_%s++;", st_lower (def->name));
1813 dump (0, "continue;");
1814 dump (-1, "case 2:");
1817 dump (-1, "default:");
1819 dump (0, "NOT_REACHED ();");
1827 for (sbc = subcommands; sbc; sbc = sbc->next)
1829 dump (1, "%sif (%s)", f ? "else " : "", make_match (sbc->name));
1833 dump (0, "lex_match (lexer, '=');");
1834 dump (0, "p->sbc_%s++;", st_lower (sbc->name));
1835 if (sbc->arity != ARITY_MANY)
1837 dump (1, "if (p->sbc_%s > 1)", st_lower (sbc->name));
1839 dump (0, "msg (SE, _(\"%s subcommand may be given only once.\"));",
1841 dump (0, "goto lossage;");
1845 dump_subcommand (sbc);
1852 /* Now deal with the /ALGORITHM subcommand implicit to all commands */
1853 dump(1,"else if ( get_syntax() != COMPATIBLE && lex_match_id(lexer, \"ALGORITHM\"))");
1856 dump (0, "lex_match (lexer, '=');");
1858 dump(1,"if (lex_match_id(lexer, \"COMPATIBLE\"))");
1859 dump(0,"set_cmd_algorithm(COMPATIBLE);");
1861 dump(1,"else if (lex_match_id(lexer, \"ENHANCED\"))");
1862 dump(0,"set_cmd_algorithm(ENHANCED);");
1869 dump (1, "if (!lex_match (lexer, '/'))");
1874 dump (1, "if (lex_token (lexer) != '.')");
1876 dump (0, "lex_error (lexer, _(\"expecting end of command\"));");
1877 dump (0, "goto lossage;");
1884 /* Check that mandatory subcommands have been specified */
1887 for (sbc = subcommands; sbc; sbc = sbc->next)
1890 if ( sbc->arity == ARITY_ONCE_EXACTLY )
1892 dump (0, "if ( 0 == p->sbc_%s)", st_lower (sbc->name));
1894 dump (0, "msg (SE, _(\"%s subcommand must be given.\"));",
1896 dump (0, "goto lossage;");
1903 dump (-1, "return true;");
1905 dump (-1, "lossage:");
1907 dump (0, "free_%s (p);", make_identifier (cmdname));
1908 dump (0, "return false;");
1914 /* Write the output file header. */
1919 dump (0, "/* %s\t\t-*- mode: c; buffer-read-only: t -*-", ofn);
1921 dump (0, " Generated by q2c from %s.", ifn);
1922 dump (0, " Do not modify!");
1926 /* Write out commands to free variable state. */
1928 dump_free (int persistent)
1938 for (sbc = subcommands; sbc; sbc = sbc->next)
1939 used = (sbc->type == SBC_STRING
1940 || sbc->type == SBC_DBL_LIST
1941 || sbc->type == SBC_INT_LIST);
1944 dump (0, "static void");
1945 dump (0, "free_%s (struct cmd_%s *p%s)", make_identifier (cmdname),
1946 make_identifier (cmdname), used ? "" : " UNUSED");
1952 for (sbc = subcommands; sbc; sbc = sbc->next)
1957 dump (0, "free (p->v_%s);", st_lower (sbc->name));
1960 dump (0, "free (p->s_%s);", st_lower (sbc->name));
1966 dump (2, "for(i = 0; i < MAXLISTS ; ++i)");
1967 dump (1, "subc_list_%s_destroy(&p->%cl_%s[i]);",
1968 sbc->type == SBC_INT_LIST ? "int" : "double",
1969 sbc->type == SBC_INT_LIST ? 'i' : 'd',
1970 st_lower (sbc->name));
1979 for (spec = sbc->spec; spec; spec = spec->next)
1980 for (s = spec->s; s; s = s->next)
1981 if (s->value == VAL_STRING)
1982 dump (0, "free (p->%s%s);",
1983 sbc->prefix, st_lower (s->valname));
1997 /* Returns the name of a directive found on the current input line, if
1998 any, or a null pointer if none found. */
2000 recognize_directive (void)
2002 static char directive[16];
2006 if (strncmp (sp, "/*", 2))
2008 sp = skip_ws (sp + 2);
2013 ep = strchr (sp, ')');
2019 memcpy (directive, sp, ep - sp);
2020 directive[ep - sp] = '\0';
2025 main (int argc, char *argv[])
2027 program_name = argv[0];
2029 fail ("Syntax: q2c input.q output.c");
2032 in = fopen (ifn, "r");
2034 fail ("%s: open: %s.", ifn, strerror (errno));
2037 out = fopen (ofn, "w");
2039 fail ("%s: open: %s.", ofn, strerror (errno));
2042 buf = xmalloc (MAX_LINE_LEN);
2043 tokstr = xmalloc (MAX_TOK_LEN);
2049 dump (0, "#line %d \"%s\"", ln + 1, ifn);
2052 const char *directive = recognize_directive ();
2053 if (directive == NULL)
2055 dump (0, "%s", buf);
2059 dump (0, "#line %d \"%s\"", oln + 1, ofn);
2060 if (!strcmp (directive, "specification"))
2062 /* Skip leading slash-star line. */
2068 /* Skip trailing star-slash line. */
2071 else if (!strcmp (directive, "headers"))
2075 dump (0, "#include <stdlib.h>");
2076 dump (0, "#include <libpspp/assertion.h>");
2077 dump (0, "#include <libpspp/message.h>");
2078 dump (0, "#include <language/lexer/lexer.h>");
2079 dump (0, "#include <language/lexer/variable-parser.h>");
2080 dump (0, "#include <data/settings.h>");
2081 dump (0, "#include <libpspp/str.h>");
2082 dump (0, "#include <language/lexer/subcommand-list.h>");
2083 dump (0, "#include <data/variable.h>");
2086 dump (0, "#include \"xalloc.h\"");
2089 dump (0, "#include \"gettext.h\"");
2090 dump (0, "#define _(msgid) gettext (msgid)");
2093 else if (!strcmp (directive, "declarations"))
2094 dump_declarations ();
2095 else if (!strcmp (directive, "functions"))
2100 else if (!strcmp (directive, "_functions"))
2106 error ("unknown directive `%s'", directive);
2108 dump (0, "#line %d \"%s\"", ln + 1, ifn);
2111 return EXIT_SUCCESS;