diff --git a/xcpt.c b/xcpt.c
index 3623709940b8c2294981586ebd36c327c04ad996..ab529cd8426d34334a3fffcd925c3c06f066451b 100644
--- a/xcpt.c
+++ b/xcpt.c
@@ -89,7 +89,10 @@ static char *xstrdup(const char *x)
 	O(TRAYFEED, "stack") \
 	O(MEDIATYPE, "system-default") \
 	O(MEDIAXSIZE, "21000") \
-	O(MEDIAYSIZE, "29700")
+	O(MEDIAYSIZE, "29700") \
+	O(FINISH_STAPLE, "") \
+	O(FINISH_PUNCH, "") \
+	O(FINISH_FOLD, "")
 
 enum option {
 #define O(name, val) OPT_##name,
@@ -111,6 +114,7 @@ char *opt[] = {
 };
 
 #define OPT(name) opt[OPT_##name]
+#define OPT_INT(name) atoi(opt[OPT_##name])
 #define OPT_IS(name, val) !strcasecmp(OPT(name), val)
 #define OPT_IS_SET(name) *OPT(name)
 #define OPT_IS_TRUE(name) OPT_IS(name, "yes")
@@ -160,9 +164,9 @@ static char *get_token(char **pp)
   if (!*p)
     return NULL;
   int c = my_toupper(*p);
-  if (c >= 'A' && c <= 'Z' || c >= '0' && c <= '9')
+  if (c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_')
     {
-      while (c >= 'A' && c <= 'Z' || c >= '0' && c <= '9')
+      while (c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_')
 	{
 	  *tok++ = c;
 	  c = my_toupper(*++p);
@@ -367,6 +371,16 @@ static void xcpt_name(const char *name, const char *text)
   printf("</%s>\n", name);
 }
 
+static void gen_finishings(const char *opt)
+{
+  int fin, n;
+  while (sscanf(opt, "%d%n", &fin, &n) > 0)
+    {
+      xcpt_enum("value", fin);
+      opt += n;
+    }
+}
+
 static void gen_job_template(void)
 {
   // Color adjustments
@@ -387,7 +401,7 @@ static void gen_job_template(void)
       xcpt_keyword("color-effects-type", "monochrome-grayscale");
     }
 
-  xcpt_integer("copies", atoi(OPT(COPIES)));
+  xcpt_integer("copies", OPT_INT(COPIES));
 
   if (OPT_IS_SET(ORIENTATION))
     xcpt_keyword("document-reading-orientation", OPT(ORIENTATION));
@@ -407,7 +421,15 @@ static void gen_job_template(void)
    *	1004 = single-fold outside
    */
   xcpt_set_open("finishings");
-  xcpt_enum("value", 3);
+  if (OPT_IS_SET(FINISH_FOLD))
+    gen_finishings(OPT(FINISH_FOLD));
+  else if (OPT_IS_SET(FINISH_STAPLE) || OPT_IS_SET(FINISH_PUNCH))
+    {
+      gen_finishings(OPT(FINISH_STAPLE));
+      gen_finishings(OPT(FINISH_PUNCH));
+    }
+  else
+    xcpt_enum("value", 3);
   xcpt_close();
 
   xcpt_keyword("halftone-text", "ignore-pdl");
@@ -442,8 +464,8 @@ static void gen_job_template(void)
     xcpt_keyword("tray-feed", OPT(TRAYFEED));
     xcpt_keyword("media-color", OPT(MEDIACOLOR));
     xcpt_collection_open("media-size");
-      xcpt_integer("x-dimension", atoi(OPT(MEDIAXSIZE)));
-      xcpt_integer("y-dimension", atoi(OPT(MEDIAYSIZE)));
+      xcpt_integer("x-dimension", OPT_INT(MEDIAXSIZE));
+      xcpt_integer("y-dimension", OPT_INT(MEDIAYSIZE));
       xcpt_close();
     xcpt_keyword("media-type", OPT(MEDIATYPE));
     xcpt_close();