]> git.sur5r.net Git - i3/i3/commitdiff
Merge pull request #1965 from Airblader/feature-typed-commands-parser
authorMichael Stapelberg <stapelberg@users.noreply.github.com>
Sun, 4 Oct 2015 15:05:27 +0000 (17:05 +0200)
committerMichael Stapelberg <stapelberg@users.noreply.github.com>
Sun, 4 Oct 2015 15:05:27 +0000 (17:05 +0200)
Make the command parser stack typed

include/commands.h
include/startup.h
include/workspace.h
parser-specs/commands.spec
src/commands.c
src/commands_parser.c
src/config_parser.c
src/startup.c
src/workspace.c
testcases/t/187-commands-parser.t

index 80b0efb020e91dfe00c278cb1e56116b48b3fb63..e0bb2f9279b15c6e3b7f69ac2deab83ac1fc9fd0 100644 (file)
@@ -33,14 +33,14 @@ void cmd_criteria_match_windows(I3_CMD);
  * specification.
  *
  */
-void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue);
+void cmd_criteria_add(I3_CMD, const char *ctype, const char *cvalue);
 
 /**
  * Implementation of 'move [window|container] [to] workspace
  * next|prev|next_on_output|prev_on_output'.
  *
  */
-void cmd_move_con_to_workspace(I3_CMD, char *which);
+void cmd_move_con_to_workspace(I3_CMD, const char *which);
 
 /**
  * Implementation of 'move [window|container] [to] workspace back_and_forth'.
@@ -52,55 +52,55 @@ void cmd_move_con_to_workspace_back_and_forth(I3_CMD);
  * Implementation of 'move [window|container] [to] workspace <name>'.
  *
  */
-void cmd_move_con_to_workspace_name(I3_CMD, char *name);
+void cmd_move_con_to_workspace_name(I3_CMD, const char *name);
 
 /**
  * Implementation of 'move [window|container] [to] workspace number <number>'.
  *
  */
-void cmd_move_con_to_workspace_number(I3_CMD, char *which);
+void cmd_move_con_to_workspace_number(I3_CMD, const char *which);
 
 /**
  * Implementation of 'resize set <px> [px] <px> [px]'.
  *
  */
-void cmd_size(I3_CMD, char *cwidth, char *cheight);
+void cmd_resize_set(I3_CMD, long cwidth, long cheight);
 
 /**
  * Implementation of 'resize grow|shrink <direction> [<px> px] [or <ppt> ppt]'.
  *
  */
-void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resize_ppt);
+void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px, long resize_ppt);
 
 /**
  * Implementation of 'border normal|pixel [<n>]', 'border none|1pixel|toggle'.
  *
  */
-void cmd_border(I3_CMD, char *border_style_str, char *border_width);
+void cmd_border(I3_CMD, const char *border_style_str, const char *border_width);
 
 /**
  * Implementation of 'nop <comment>'.
  *
  */
-void cmd_nop(I3_CMD, char *comment);
+void cmd_nop(I3_CMD, const char *comment);
 
 /**
  * Implementation of 'append_layout <path>'.
  *
  */
-void cmd_append_layout(I3_CMD, char *path);
+void cmd_append_layout(I3_CMD, const char *path);
 
 /**
  * Implementation of 'workspace next|prev|next_on_output|prev_on_output'.
  *
  */
-void cmd_workspace(I3_CMD, char *which);
+void cmd_workspace(I3_CMD, const char *which);
 
 /**
  * Implementation of 'workspace number <number>'
  *
  */
-void cmd_workspace_number(I3_CMD, char *which);
+void cmd_workspace_number(I3_CMD, const char *which);
 
 /**
  * Implementation of 'workspace back_and_forth'.
@@ -112,85 +112,85 @@ void cmd_workspace_back_and_forth(I3_CMD);
  * Implementation of 'workspace <name>'
  *
  */
-void cmd_workspace_name(I3_CMD, char *name);
+void cmd_workspace_name(I3_CMD, const char *name);
 
 /**
  * Implementation of 'mark [--toggle] <mark>'
  *
  */
-void cmd_mark(I3_CMD, char *mark, char *toggle);
+void cmd_mark(I3_CMD, const char *mark, const char *toggle);
 
 /**
  * Implementation of 'unmark [mark]'
  *
  */
-void cmd_unmark(I3_CMD, char *mark);
+void cmd_unmark(I3_CMD, const char *mark);
 
 /**
  * Implementation of 'mode <string>'.
  *
  */
-void cmd_mode(I3_CMD, char *mode);
+void cmd_mode(I3_CMD, const char *mode);
 
 /**
  * Implementation of 'move [window|container] [to] output <str>'.
  *
  */
-void cmd_move_con_to_output(I3_CMD, char *name);
+void cmd_move_con_to_output(I3_CMD, const char *name);
 
 /**
  * Implementation of 'move [window|container] [to] mark <str>'.
  *
  */
-void cmd_move_con_to_mark(I3_CMD, char *mark);
+void cmd_move_con_to_mark(I3_CMD, const char *mark);
 
 /**
  * Implementation of 'floating enable|disable|toggle'
  *
  */
-void cmd_floating(I3_CMD, char *floating_mode);
+void cmd_floating(I3_CMD, const char *floating_mode);
 
 /**
  * Implementation of 'move workspace to [output] <str>'.
  *
  */
-void cmd_move_workspace_to_output(I3_CMD, char *name);
+void cmd_move_workspace_to_output(I3_CMD, const char *name);
 
 /**
  * Implementation of 'split v|h|vertical|horizontal'.
  *
  */
-void cmd_split(I3_CMD, char *direction);
+void cmd_split(I3_CMD, const char *direction);
 
 /**
  * Implementation of 'kill [window|client]'.
  *
  */
-void cmd_kill(I3_CMD, char *kill_mode_str);
+void cmd_kill(I3_CMD, const char *kill_mode_str);
 
 /**
  * Implementation of 'exec [--no-startup-id] <command>'.
  *
  */
-void cmd_exec(I3_CMD, char *nosn, char *command);
+void cmd_exec(I3_CMD, const char *nosn, const char *command);
 
 /**
  * Implementation of 'focus left|right|up|down'.
  *
  */
-void cmd_focus_direction(I3_CMD, char *direction);
+void cmd_focus_direction(I3_CMD, const char *direction);
 
 /**
  * Implementation of 'focus tiling|floating|mode_toggle'.
  *
  */
-void cmd_focus_window_mode(I3_CMD, char *window_mode);
+void cmd_focus_window_mode(I3_CMD, const char *window_mode);
 
 /**
  * Implementation of 'focus parent|child'.
  *
  */
-void cmd_focus_level(I3_CMD, char *level);
+void cmd_focus_level(I3_CMD, const char *level);
 
 /**
  * Implementation of 'focus'.
@@ -202,31 +202,31 @@ void cmd_focus(I3_CMD);
  * Implementation of 'fullscreen [enable|disable|toggle] [global]'.
  *
  */
-void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode);
+void cmd_fullscreen(I3_CMD, const char *action, const char *fullscreen_mode);
 
 /**
  * Implementation of 'sticky enable|disable|toggle'.
  *
  */
-void cmd_sticky(I3_CMD, char *action);
+void cmd_sticky(I3_CMD, const char *action);
 
 /**
  * Implementation of 'move <direction> [<pixels> [px]]'.
  *
  */
-void cmd_move_direction(I3_CMD, char *direction, char *move_px);
+void cmd_move_direction(I3_CMD, const char *direction, long move_px);
 
 /**
  * Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
  *
  */
-void cmd_layout(I3_CMD, char *layout_str);
+void cmd_layout(I3_CMD, const char *layout_str);
 
 /**
  * Implementation of 'layout toggle [all|split]'.
  *
  */
-void cmd_layout_toggle(I3_CMD, char *toggle_mode);
+void cmd_layout_toggle(I3_CMD, const char *toggle_mode);
 
 /**
  * Implementation of 'exit'.
@@ -256,19 +256,19 @@ void cmd_open(I3_CMD);
  * Implementation of 'focus output <output>'.
  *
  */
-void cmd_focus_output(I3_CMD, char *name);
+void cmd_focus_output(I3_CMD, const char *name);
 
 /**
  * Implementation of 'move [window|container] [to] [absolute] position <px> [px] <px> [px]
  *
  */
-void cmd_move_window_to_position(I3_CMD, char *method, char *x, char *y);
+void cmd_move_window_to_position(I3_CMD, const char *method, long x, long y);
 
 /**
  * Implementation of 'move [window|container] [to] [absolute] position center
  *
  */
-void cmd_move_window_to_center(I3_CMD, char *method);
+void cmd_move_window_to_center(I3_CMD, const char *method);
 
 /**
  * Implementation of 'move [window|container] [to] position mouse'
@@ -292,28 +292,28 @@ void cmd_scratchpad_show(I3_CMD);
  * Implementation of 'title_format <format>'
  *
  */
-void cmd_title_format(I3_CMD, char *format);
+void cmd_title_format(I3_CMD, const char *format);
 
 /**
  * Implementation of 'rename workspace <name> to <name>'
  *
  */
-void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name);
+void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name);
 
 /**
  * Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
  *
  */
-void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id);
+void cmd_bar(I3_CMD, const char *bar_type, const char *bar_value, const char *bar_id);
 
 /*
  * Implementation of 'shmlog <size>|toggle|on|off'
  *
  */
-void cmd_shmlog(I3_CMD, char *argument);
+void cmd_shmlog(I3_CMD, const char *argument);
 
 /*
  * Implementation of 'debuglog toggle|on|off'
  *
  */
-void cmd_debuglog(I3_CMD, char *argument);
+void cmd_debuglog(I3_CMD, const char *argument);
index 7d5d2a39644abf350b8c3191b48a9490654bfe8c..9729cdc2fcd7c2c03eae53dc81419bbf13d82266 100644 (file)
@@ -48,7 +48,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata);
  * Renames workspaces that are mentioned in the startup sequences.
  *
  */
-void startup_sequence_rename_workspace(char *old_name, char *new_name);
+void startup_sequence_rename_workspace(const char *old_name, const char *new_name);
 
 /**
  * Gets the stored startup sequence for the _NET_STARTUP_ID of a given window.
index 21ab18d69d5043e663312ce1141495410db0a88c..1bee64e08d5cf81f08612e90a76fb1bc8bc8cb6a 100644 (file)
@@ -194,4 +194,4 @@ Con *workspace_encapsulate(Con *ws);
  * This returns true if and only if moving the workspace was successful.
  *
  */
-bool workspace_move_to_output(Con *ws, char *output);
+bool workspace_move_to_output(Con *ws, const char *output);
index 5e2bfd8f0b0296373c6be9bba040e1f3a469669a..b3b5e3385fafc09259463d85367a8d404dc0b10a 100644 (file)
@@ -225,10 +225,10 @@ state RESIZE_DIRECTION:
       -> RESIZE_PX
 
 state RESIZE_PX:
-  resize_px = word
+  resize_px = number
       -> RESIZE_TILING
   end
-      -> call cmd_resize($way, $direction, "10", "10")
+      -> call cmd_resize($way, $direction, 10, 10)
 
 state RESIZE_TILING:
   'px'
@@ -236,29 +236,29 @@ state RESIZE_TILING:
   'or'
       -> RESIZE_TILING_OR
   end
-      -> call cmd_resize($way, $direction, $resize_px, "10")
+      -> call cmd_resize($way, $direction, &resize_px, 10)
 
 state RESIZE_TILING_OR:
-  resize_ppt = word
+  resize_ppt = number
       -> RESIZE_TILING_FINAL
 
 state RESIZE_TILING_FINAL:
   'ppt', end
-      -> call cmd_resize($way, $direction, $resize_px, $resize_ppt)
+      -> call cmd_resize($way, $direction, &resize_px, &resize_ppt)
 
 state RESIZE_SET:
-  width = word
+  width = number
       -> RESIZE_WIDTH
 
 state RESIZE_WIDTH:
   'px'
       ->
-  height = word
+  height = number
       -> RESIZE_HEIGHT
 
 state RESIZE_HEIGHT:
   'px', end
-      -> call cmd_size($width, $height)
+      -> call cmd_resize_set(&width, &height)
 
 # rename workspace <name> to <name>
 # rename workspace to <name>
@@ -320,16 +320,16 @@ state MOVE:
       -> MOVE_TO_ABSOLUTE_POSITION
 
 state MOVE_DIRECTION:
-  pixels = word
+  pixels = number
       -> MOVE_DIRECTION_PX
   end
-      -> call cmd_move_direction($direction, "10")
+      -> call cmd_move_direction($direction, 10)
 
 state MOVE_DIRECTION_PX:
   'px'
-      -> call cmd_move_direction($direction, $pixels)
+      -> call cmd_move_direction($direction, &pixels)
   end
-      -> call cmd_move_direction($direction, $pixels)
+      -> call cmd_move_direction($direction, &pixels)
 
 state MOVE_WORKSPACE:
   'to '
@@ -370,18 +370,18 @@ state MOVE_TO_POSITION:
       -> call cmd_move_window_to_center($method)
   'mouse', 'cursor', 'pointer'
       -> call cmd_move_window_to_mouse()
-  coord_x = word
+  coord_x = number
       -> MOVE_TO_POSITION_X
 
 state MOVE_TO_POSITION_X:
   'px'
       ->
-  coord_y = word
+  coord_y = number
       -> MOVE_TO_POSITION_Y
 
 state MOVE_TO_POSITION_Y:
   'px', end
-      -> call cmd_move_window_to_position($method, $coord_x, $coord_y)
+      -> call cmd_move_window_to_position($method, &coord_x, &coord_y)
 
 # mode <string>
 state MODE:
index a696ad34a083b7258ee2e26cae1e45ba7eb0061e..95784c773d0273cd1fed12a8be0b510688c4eb62 100644 (file)
@@ -83,7 +83,7 @@ static Output *get_output_of_con(Con *con) {
  * and return true, signaling that no further workspace switching should occur in the calling function.
  *
  */
-static bool maybe_back_and_forth(struct CommandResultIR *cmd_output, char *name) {
+static bool maybe_back_and_forth(struct CommandResultIR *cmd_output, const char *name) {
     Con *ws = con_get_workspace(focused);
 
     /* If we switched to a different workspace, do nothing */
@@ -315,7 +315,7 @@ void cmd_criteria_match_windows(I3_CMD) {
  * specification.
  *
  */
-void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) {
+void cmd_criteria_add(I3_CMD, const char *ctype, const char *cvalue) {
     DLOG("ctype=*%s*, cvalue=*%s*\n", ctype, cvalue);
 
     if (strcmp(ctype, "class") == 0) {
@@ -424,7 +424,7 @@ void cmd_criteria_add(I3_CMD, char *ctype, char *cvalue) {
  * next|prev|next_on_output|prev_on_output|current'.
  *
  */
-void cmd_move_con_to_workspace(I3_CMD, char *which) {
+void cmd_move_con_to_workspace(I3_CMD, const char *which) {
     owindow *current;
 
     DLOG("which=%s\n", which);
@@ -500,7 +500,7 @@ void cmd_move_con_to_workspace_back_and_forth(I3_CMD) {
  * Implementation of 'move [window|container] [to] workspace <name>'.
  *
  */
-void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
+void cmd_move_con_to_workspace_name(I3_CMD, const char *name) {
     if (strncasecmp(name, "__", strlen("__")) == 0) {
         LOG("You cannot move containers to i3-internal workspaces (\"%s\").\n", name);
         ysuccess(false);
@@ -544,7 +544,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name) {
  * Implementation of 'move [window|container] [to] workspace number <name>'.
  *
  */
-void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
+void cmd_move_con_to_workspace_number(I3_CMD, const char *which) {
     owindow *current;
 
     /* We have nothing to move:
@@ -591,7 +591,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, char *which) {
     ysuccess(true);
 }
 
-static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floating_con, int px) {
+static void cmd_resize_floating(I3_CMD, const char *way, const char *direction, Con *floating_con, int px) {
     LOG("floating resize\n");
     Rect old_rect = floating_con->rect;
     Con *focused_con = con_descend_focused(floating_con);
@@ -643,7 +643,7 @@ static void cmd_resize_floating(I3_CMD, char *way, char *direction, Con *floatin
         floating_con->scratchpad_state = SCRATCHPAD_CHANGED;
 }
 
-static bool cmd_resize_tiling_direction(I3_CMD, Con *current, char *way, char *direction, int ppt) {
+static bool cmd_resize_tiling_direction(I3_CMD, Con *current, const char *way, const char *direction, int ppt) {
     LOG("tiling resize\n");
     Con *second = NULL;
     Con *first = current;
@@ -696,7 +696,7 @@ static bool cmd_resize_tiling_direction(I3_CMD, Con *current, char *way, char *d
     return true;
 }
 
-static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, char *way, char *direction, int ppt) {
+static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way, const char *direction, int ppt) {
     LOG("width/height resize\n");
     /* get the appropriate current container (skip stacked/tabbed cons) */
     while (current->parent->layout == L_STACKED ||
@@ -782,15 +782,11 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, char *way, char
  * Implementation of 'resize grow|shrink <direction> [<px> px] [or <ppt> ppt]'.
  *
  */
-void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resize_ppt) {
-    /* resize <grow|shrink> <direction> [<px> px] [or <ppt> ppt] */
-    DLOG("resizing in way %s, direction %s, px %s or ppt %s\n", way, direction, resize_px, resize_ppt);
-    // TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking
-    int px = atoi(resize_px);
-    int ppt = atoi(resize_ppt);
+void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px, long resize_ppt) {
+    DLOG("resizing in way %s, direction %s, px %ld or ppt %ld\n", way, direction, resize_px, resize_ppt);
     if (strcmp(way, "shrink") == 0) {
-        px *= -1;
-        ppt *= -1;
+        resize_px *= -1;
+        resize_ppt *= -1;
     }
 
     HANDLE_EMPTY_MATCH;
@@ -805,14 +801,16 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
 
         Con *floating_con;
         if ((floating_con = con_inside_floating(current->con))) {
-            cmd_resize_floating(current_match, cmd_output, way, direction, floating_con, px);
+            cmd_resize_floating(current_match, cmd_output, way, direction, floating_con, resize_px);
         } else {
             if (strcmp(direction, "width") == 0 ||
                 strcmp(direction, "height") == 0) {
-                if (!cmd_resize_tiling_width_height(current_match, cmd_output, current->con, way, direction, ppt))
+                if (!cmd_resize_tiling_width_height(current_match, cmd_output,
+                                                    current->con, way, direction, resize_ppt))
                     return;
             } else {
-                if (!cmd_resize_tiling_direction(current_match, cmd_output, current->con, way, direction, ppt))
+                if (!cmd_resize_tiling_direction(current_match, cmd_output,
+                                                 current->con, way, direction, resize_ppt))
                     return;
             }
         }
@@ -827,13 +825,10 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz
  * Implementation of 'resize set <px> [px] <px> [px]'.
  *
  */
-void cmd_size(I3_CMD, char *cwidth, char *cheight) {
-    DLOG("resizing to %sx%s px\n", cwidth, cheight);
-    // TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking
-    int x = atoi(cwidth);
-    int y = atoi(cheight);
-    if (x <= 0 || y <= 0) {
-        ELOG("Resize failed: dimensions cannot be negative (was %sx%s)\n", cwidth, cheight);
+void cmd_resize_set(I3_CMD, long cwidth, long cheight) {
+    DLOG("resizing to %ldx%ld px\n", cwidth, cheight);
+    if (cwidth <= 0 || cheight <= 0) {
+        ELOG("Resize failed: dimensions cannot be negative (was %ldx%ld)\n", cwidth, cheight);
         return;
     }
 
@@ -843,7 +838,7 @@ void cmd_size(I3_CMD, char *cwidth, char *cheight) {
     TAILQ_FOREACH(current, &owindows, owindows) {
         Con *floating_con;
         if ((floating_con = con_inside_floating(current->con))) {
-            floating_resize(floating_con, x, y);
+            floating_resize(floating_con, cwidth, cheight);
         } else {
             ELOG("Resize failed: %p not a floating container\n", current->con);
         }
@@ -858,7 +853,7 @@ void cmd_size(I3_CMD, char *cwidth, char *cheight) {
  * Implementation of 'border normal|pixel [<n>]', 'border none|1pixel|toggle'.
  *
  */
-void cmd_border(I3_CMD, char *border_style_str, char *border_width) {
+void cmd_border(I3_CMD, const char *border_style_str, const char *border_width) {
     DLOG("border style should be changed to %s with border width %s\n", border_style_str, border_width);
     owindow *current;
 
@@ -911,7 +906,7 @@ void cmd_border(I3_CMD, char *border_style_str, char *border_width) {
  * Implementation of 'nop <comment>'.
  *
  */
-void cmd_nop(I3_CMD, char *comment) {
+void cmd_nop(I3_CMD, const char *comment) {
     LOG("-------------------------------------------------\n");
     LOG("  NOP: %s\n", comment);
     LOG("-------------------------------------------------\n");
@@ -921,7 +916,8 @@ void cmd_nop(I3_CMD, char *comment) {
  * Implementation of 'append_layout <path>'.
  *
  */
-void cmd_append_layout(I3_CMD, char *path) {
+void cmd_append_layout(I3_CMD, const char *cpath) {
+    char *path = sstrdup(cpath);
     LOG("Appending layout \"%s\"\n", path);
 
     /* Make sure we allow paths like '~/.i3/layout.json' */
@@ -982,7 +978,7 @@ void cmd_append_layout(I3_CMD, char *path) {
  * Implementation of 'workspace next|prev|next_on_output|prev_on_output'.
  *
  */
-void cmd_workspace(I3_CMD, char *which) {
+void cmd_workspace(I3_CMD, const char *which) {
     Con *ws;
 
     DLOG("which=%s\n", which);
@@ -1018,7 +1014,7 @@ void cmd_workspace(I3_CMD, char *which) {
  * Implementation of 'workspace number <name>'
  *
  */
-void cmd_workspace_number(I3_CMD, char *which) {
+void cmd_workspace_number(I3_CMD, const char *which) {
     Con *output, *workspace = NULL;
 
     if (con_get_fullscreen_con(croot, CF_GLOBAL)) {
@@ -1077,7 +1073,7 @@ void cmd_workspace_back_and_forth(I3_CMD) {
  * Implementation of 'workspace <name>'
  *
  */
-void cmd_workspace_name(I3_CMD, char *name) {
+void cmd_workspace_name(I3_CMD, const char *name) {
     if (strncasecmp(name, "__", strlen("__")) == 0) {
         LOG("You cannot switch to the i3-internal workspaces (\"%s\").\n", name);
         ysuccess(false);
@@ -1104,7 +1100,7 @@ void cmd_workspace_name(I3_CMD, char *name) {
  * Implementation of 'mark [--toggle] <mark>'
  *
  */
-void cmd_mark(I3_CMD, char *mark, char *toggle) {
+void cmd_mark(I3_CMD, const char *mark, const char *toggle) {
     HANDLE_EMPTY_MATCH;
 
     owindow *current = TAILQ_FIRST(&owindows);
@@ -1135,7 +1131,7 @@ void cmd_mark(I3_CMD, char *mark, char *toggle) {
  * Implementation of 'unmark [mark]'
  *
  */
-void cmd_unmark(I3_CMD, char *mark) {
+void cmd_unmark(I3_CMD, const char *mark) {
     con_unmark(mark);
 
     cmd_output->needs_tree_render = true;
@@ -1147,7 +1143,7 @@ void cmd_unmark(I3_CMD, char *mark) {
  * Implementation of 'mode <string>'.
  *
  */
-void cmd_mode(I3_CMD, char *mode) {
+void cmd_mode(I3_CMD, const char *mode) {
     DLOG("mode=%s\n", mode);
     switch_mode(mode);
 
@@ -1159,7 +1155,7 @@ void cmd_mode(I3_CMD, char *mode) {
  * Implementation of 'move [window|container] [to] output <str>'.
  *
  */
-void cmd_move_con_to_output(I3_CMD, char *name) {
+void cmd_move_con_to_output(I3_CMD, const char *name) {
     DLOG("Should move window to output \"%s\".\n", name);
     HANDLE_EMPTY_MATCH;
 
@@ -1197,7 +1193,7 @@ void cmd_move_con_to_output(I3_CMD, char *name) {
  * Implementation of 'move [container|window] [to] mark <str>'.
  *
  */
-void cmd_move_con_to_mark(I3_CMD, char *mark) {
+void cmd_move_con_to_mark(I3_CMD, const char *mark) {
     DLOG("moving window to mark \"%s\"\n", mark);
 
     HANDLE_EMPTY_MATCH;
@@ -1217,7 +1213,7 @@ void cmd_move_con_to_mark(I3_CMD, char *mark) {
  * Implementation of 'floating enable|disable|toggle'
  *
  */
-void cmd_floating(I3_CMD, char *floating_mode) {
+void cmd_floating(I3_CMD, const char *floating_mode) {
     owindow *current;
 
     DLOG("floating_mode=%s\n", floating_mode);
@@ -1248,7 +1244,7 @@ void cmd_floating(I3_CMD, char *floating_mode) {
  * Implementation of 'move workspace to [output] <str>'.
  *
  */
-void cmd_move_workspace_to_output(I3_CMD, char *name) {
+void cmd_move_workspace_to_output(I3_CMD, const char *name) {
     DLOG("should move workspace to output %s\n", name);
 
     HANDLE_EMPTY_MATCH;
@@ -1273,7 +1269,7 @@ void cmd_move_workspace_to_output(I3_CMD, char *name) {
  * Implementation of 'split v|h|vertical|horizontal'.
  *
  */
-void cmd_split(I3_CMD, char *direction) {
+void cmd_split(I3_CMD, const char *direction) {
     owindow *current;
     /* TODO: use matches */
     LOG("splitting in direction %c\n", direction[0]);
@@ -1295,7 +1291,7 @@ void cmd_split(I3_CMD, char *direction) {
  * Implementation of 'kill [window|client]'.
  *
  */
-void cmd_kill(I3_CMD, char *kill_mode_str) {
+void cmd_kill(I3_CMD, const char *kill_mode_str) {
     if (kill_mode_str == NULL)
         kill_mode_str = "window";
     owindow *current;
@@ -1332,7 +1328,7 @@ void cmd_kill(I3_CMD, char *kill_mode_str) {
  * Implementation of 'exec [--no-startup-id] <command>'.
  *
  */
-void cmd_exec(I3_CMD, char *nosn, char *command) {
+void cmd_exec(I3_CMD, const char *nosn, const char *command) {
     bool no_startup_id = (nosn != NULL);
 
     DLOG("should execute %s, no_startup_id = %d\n", command, no_startup_id);
@@ -1346,7 +1342,7 @@ void cmd_exec(I3_CMD, char *nosn, char *command) {
  * Implementation of 'focus left|right|up|down'.
  *
  */
-void cmd_focus_direction(I3_CMD, char *direction) {
+void cmd_focus_direction(I3_CMD, const char *direction) {
     DLOG("direction = *%s*\n", direction);
 
     if (strcmp(direction, "left") == 0)
@@ -1372,7 +1368,7 @@ void cmd_focus_direction(I3_CMD, char *direction) {
  * Implementation of 'focus tiling|floating|mode_toggle'.
  *
  */
-void cmd_focus_window_mode(I3_CMD, char *window_mode) {
+void cmd_focus_window_mode(I3_CMD, const char *window_mode) {
     DLOG("window_mode = %s\n", window_mode);
 
     Con *ws = con_get_workspace(focused);
@@ -1403,7 +1399,7 @@ void cmd_focus_window_mode(I3_CMD, char *window_mode) {
  * Implementation of 'focus parent|child'.
  *
  */
-void cmd_focus_level(I3_CMD, char *level) {
+void cmd_focus_level(I3_CMD, const char *level) {
     DLOG("level = %s\n", level);
     bool success = false;
 
@@ -1507,7 +1503,7 @@ void cmd_focus(I3_CMD) {
  *                   'fullscreen disable'
  *
  */
-void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode) {
+void cmd_fullscreen(I3_CMD, const char *action, const char *fullscreen_mode) {
     fullscreen_mode_t mode = strcmp(fullscreen_mode, "global") == 0 ? CF_GLOBAL : CF_OUTPUT;
     DLOG("%s fullscreen, mode = %s\n", action, fullscreen_mode);
     owindow *current;
@@ -1534,7 +1530,7 @@ void cmd_fullscreen(I3_CMD, char *action, char *fullscreen_mode) {
  * Implementation of 'sticky enable|disable|toggle'.
  *
  */
-void cmd_sticky(I3_CMD, char *action) {
+void cmd_sticky(I3_CMD, const char *action) {
     DLOG("%s sticky on window\n", action);
     HANDLE_EMPTY_MATCH;
 
@@ -1570,28 +1566,25 @@ void cmd_sticky(I3_CMD, char *action) {
  * Implementation of 'move <direction> [<pixels> [px]]'.
  *
  */
-void cmd_move_direction(I3_CMD, char *direction, char *move_px) {
-    // TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking
-    int px = atoi(move_px);
-
+void cmd_move_direction(I3_CMD, const char *direction, long move_px) {
     owindow *current;
     HANDLE_EMPTY_MATCH;
 
     Con *initially_focused = focused;
 
     TAILQ_FOREACH(current, &owindows, owindows) {
-        DLOG("moving in direction %s, px %s\n", direction, move_px);
+        DLOG("moving in direction %s, px %ld\n", direction, move_px);
         if (con_is_floating(current->con)) {
-            DLOG("floating move with %d pixels\n", px);
+            DLOG("floating move with %ld pixels\n", move_px);
             Rect newrect = current->con->parent->rect;
             if (strcmp(direction, "left") == 0) {
-                newrect.x -= px;
+                newrect.x -= move_px;
             } else if (strcmp(direction, "right") == 0) {
-                newrect.x += px;
+                newrect.x += move_px;
             } else if (strcmp(direction, "up") == 0) {
-                newrect.y -= px;
+                newrect.y -= move_px;
             } else if (strcmp(direction, "down") == 0) {
-                newrect.y += px;
+                newrect.y += move_px;
             }
             floating_reposition(current->con->parent, newrect);
         } else {
@@ -1612,7 +1605,7 @@ void cmd_move_direction(I3_CMD, char *direction, char *move_px) {
  * Implementation of 'layout default|stacked|stacking|tabbed|splitv|splith'.
  *
  */
-void cmd_layout(I3_CMD, char *layout_str) {
+void cmd_layout(I3_CMD, const char *layout_str) {
     if (strcmp(layout_str, "stacking") == 0)
         layout_str = "stacked";
     owindow *current;
@@ -1654,7 +1647,7 @@ void cmd_layout(I3_CMD, char *layout_str) {
  * Implementation of 'layout toggle [all|split]'.
  *
  */
-void cmd_layout_toggle(I3_CMD, char *toggle_mode) {
+void cmd_layout_toggle(I3_CMD, const char *toggle_mode) {
     owindow *current;
 
     if (toggle_mode == NULL)
@@ -1751,7 +1744,7 @@ void cmd_open(I3_CMD) {
  * Implementation of 'focus output <output>'.
  *
  */
-void cmd_focus_output(I3_CMD, char *name) {
+void cmd_focus_output(I3_CMD, const char *name) {
     owindow *current;
 
     DLOG("name = %s\n", name);
@@ -1793,9 +1786,7 @@ void cmd_focus_output(I3_CMD, char *name) {
  * Implementation of 'move [window|container] [to] [absolute] position <px> [px] <px> [px]
  *
  */
-void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
-    int x = atoi(cx);
-    int y = atoi(cy);
+void cmd_move_window_to_position(I3_CMD, const char *method, long x, long y) {
     bool has_error = false;
 
     owindow *current;
@@ -1817,7 +1808,7 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
             current->con->parent->rect.x = x;
             current->con->parent->rect.y = y;
 
-            DLOG("moving to absolute position %d %d\n", x, y);
+            DLOG("moving to absolute position %ld %ld\n", x, y);
             floating_maybe_reassign_ws(current->con->parent);
             cmd_output->needs_tree_render = true;
         }
@@ -1825,7 +1816,7 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
         if (strcmp(method, "position") == 0) {
             Rect newrect = current->con->parent->rect;
 
-            DLOG("moving to position %d %d\n", x, y);
+            DLOG("moving to position %ld %ld\n", x, y);
             newrect.x = x;
             newrect.y = y;
 
@@ -1842,7 +1833,7 @@ void cmd_move_window_to_position(I3_CMD, char *method, char *cx, char *cy) {
  * Implementation of 'move [window|container] [to] [absolute] position center
  *
  */
-void cmd_move_window_to_center(I3_CMD, char *method) {
+void cmd_move_window_to_center(I3_CMD, const char *method) {
     if (!con_is_floating(focused)) {
         ELOG("Cannot change position. The window/container is not floating\n");
         yerror("Cannot change position. The window/container is not floating.");
@@ -1938,7 +1929,7 @@ void cmd_scratchpad_show(I3_CMD) {
  * Implementation of 'title_format <format>'
  *
  */
-void cmd_title_format(I3_CMD, char *format) {
+void cmd_title_format(I3_CMD, const char *format) {
     DLOG("setting title_format to \"%s\"\n", format);
     HANDLE_EMPTY_MATCH;
 
@@ -1975,7 +1966,7 @@ void cmd_title_format(I3_CMD, char *format) {
  * Implementation of 'rename workspace [<name>] to <name>'
  *
  */
-void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
+void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
     if (strncasecmp(new_name, "__", strlen("__")) == 0) {
         LOG("Cannot rename workspace to \"%s\": names starting with __ are i3-internal.\n", new_name);
         ysuccess(false);
@@ -2060,7 +2051,7 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name) {
  * Implementation of 'bar mode dock|hide|invisible|toggle [<bar_id>]'
  *
  */
-bool cmd_bar_mode(char *bar_mode, char *bar_id) {
+bool cmd_bar_mode(const char *bar_mode, const char *bar_id) {
     int mode = M_DOCK;
     bool toggle = false;
     if (strcmp(bar_mode, "dock") == 0)
@@ -2105,7 +2096,7 @@ bool cmd_bar_mode(char *bar_mode, char *bar_id) {
  * Implementation of 'bar hidden_state hide|show|toggle [<bar_id>]'
  *
  */
-bool cmd_bar_hidden_state(char *bar_hidden_state, char *bar_id) {
+bool cmd_bar_hidden_state(const char *bar_hidden_state, const char *bar_id) {
     int hidden_state = S_SHOW;
     bool toggle = false;
     if (strcmp(bar_hidden_state, "hide") == 0)
@@ -2148,7 +2139,7 @@ bool cmd_bar_hidden_state(char *bar_hidden_state, char *bar_id) {
  * Implementation of 'bar (hidden_state hide|show|toggle)|(mode dock|hide|invisible|toggle) [<bar_id>]'
  *
  */
-void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id) {
+void cmd_bar(I3_CMD, const char *bar_type, const char *bar_value, const char *bar_id) {
     bool ret;
     if (strcmp(bar_type, "mode") == 0)
         ret = cmd_bar_mode(bar_value, bar_id);
@@ -2170,7 +2161,7 @@ void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id) {
  * Implementation of 'shmlog <size>|toggle|on|off'
  *
  */
-void cmd_shmlog(I3_CMD, char *argument) {
+void cmd_shmlog(I3_CMD, const char *argument) {
     if (!strcmp(argument, "toggle"))
         /* Toggle shm log, if size is not 0. If it is 0, set it to default. */
         shmlog_size = shmlog_size ? -shmlog_size : default_shmlog_size;
@@ -2201,7 +2192,7 @@ void cmd_shmlog(I3_CMD, char *argument) {
  * Implementation of 'debuglog toggle|on|off'
  *
  */
-void cmd_debuglog(I3_CMD, char *argument) {
+void cmd_debuglog(I3_CMD, const char *argument) {
     bool logging = get_debug_logging();
     if (!strcmp(argument, "toggle")) {
         LOG("%s debug logging\n", logging ? "Disabling" : "Enabling");
index ffe416f04dd1c3659ff0aae5687f02269ee63700..cdd35e459b904d7241cb599eb4abb55ef0e2e271 100644 (file)
@@ -73,7 +73,14 @@ typedef struct tokenptr {
 struct stack_entry {
     /* Just a pointer, not dynamically allocated. */
     const char *identifier;
-    char *str;
+    enum {
+        STACK_STR = 0,
+        STACK_LONG = 1,
+    } type;
+    union {
+        char *str;
+        long num;
+    } val;
 };
 
 /* 10 entries should be enough for everybody. */
@@ -90,7 +97,8 @@ static void push_string(const char *identifier, char *str) {
             continue;
         /* Found a free slot, let’s store it here. */
         stack[c].identifier = identifier;
-        stack[c].str = str;
+        stack[c].val.str = str;
+        stack[c].type = STACK_STR;
         return;
     }
 
@@ -103,73 +111,61 @@ static void push_string(const char *identifier, char *str) {
     exit(1);
 }
 
-// XXX: ideally, this would be const char. need to check if that works with all
-// called functions.
-static char *get_string(const char *identifier) {
+// TODO move to a common util
+static void push_long(const char *identifier, long num) {
+    for (int c = 0; c < 10; c++) {
+        if (stack[c].identifier != NULL) {
+            continue;
+        }
+
+        stack[c].identifier = identifier;
+        stack[c].val.num = num;
+        stack[c].type = STACK_LONG;
+        return;
+    }
+
+    /* When we arrive here, the stack is full. This should not happen and
+     * means there’s either a bug in this parser or the specification
+     * contains a command with more than 10 identified tokens. */
+    fprintf(stderr, "BUG: commands_parser stack full. This means either a bug "
+                    "in the code, or a new command which contains more than "
+                    "10 identified tokens.\n");
+    exit(1);
+}
+
+// TODO move to a common util
+static const char *get_string(const char *identifier) {
     for (int c = 0; c < 10; c++) {
         if (stack[c].identifier == NULL)
             break;
         if (strcmp(identifier, stack[c].identifier) == 0)
-            return stack[c].str;
+            return stack[c].val.str;
     }
     return NULL;
 }
 
-static void clear_stack(void) {
+// TODO move to a common util
+static long get_long(const char *identifier) {
     for (int c = 0; c < 10; c++) {
-        if (stack[c].str != NULL)
-            free(stack[c].str);
-        stack[c].identifier = NULL;
-        stack[c].str = NULL;
+        if (stack[c].identifier == NULL)
+            break;
+        if (strcmp(identifier, stack[c].identifier) == 0)
+            return stack[c].val.num;
     }
-}
-
-// TODO: remove this if it turns out we don’t need it for testing.
-#if 0
-/*******************************************************************************
- * A dynamically growing linked list which holds the criteria for the current
- * command.
- ******************************************************************************/
 
-typedef struct criterion {
-    char *type;
-    char *value;
-
-    TAILQ_ENTRY(criterion) criteria;
-} criterion;
-
-static TAILQ_HEAD(criteria_head, criterion) criteria =
-  TAILQ_HEAD_INITIALIZER(criteria);
-
-/*
- * Stores the given type/value in the list of criteria.
- * Accepts a pointer as first argument, since it is 'call'ed by the parser.
- *
- */
-static void push_criterion(void *unused_criteria, const char *type,
-                           const char *value) {
-    struct criterion *criterion = smalloc(sizeof(struct criterion));
-    criterion->type = sstrdup(type);
-    criterion->value = sstrdup(value);
-    TAILQ_INSERT_TAIL(&criteria, criterion, criteria);
+    return 0;
 }
 
-/*
- * Clears the criteria linked list.
- * Accepts a pointer as first argument, since it is 'call'ed by the parser.
- *
- */
-static void clear_criteria(void *unused_criteria) {
-    struct criterion *criterion;
-    while (!TAILQ_EMPTY(&criteria)) {
-        criterion = TAILQ_FIRST(&criteria);
-        free(criterion->type);
-        free(criterion->value);
-        TAILQ_REMOVE(&criteria, criterion, criteria);
-        free(criterion);
+// TODO move to a common util
+static void clear_stack(void) {
+    for (int c = 0; c < 10; c++) {
+        if (stack[c].type == STACK_STR && stack[c].val.str != NULL)
+            free(stack[c].val.str);
+        stack[c].identifier = NULL;
+        stack[c].val.str = NULL;
+        stack[c].val.num = 0;
     }
 }
-#endif
 
 /*******************************************************************************
  * The parser itself.
@@ -316,6 +312,29 @@ CommandResult *parse_command(const char *input, yajl_gen gen) {
                 continue;
             }
 
+            if (strcmp(token->name, "number") == 0) {
+                /* Handle numbers. We only accept decimal numbers for now. */
+                char *end = NULL;
+                errno = 0;
+                long int num = strtol(walk, &end, 10);
+                if ((errno == ERANGE && (num == LONG_MIN || num == LONG_MAX)) ||
+                    (errno != 0 && num == 0))
+                    continue;
+
+                /* No valid numbers found */
+                if (end == walk)
+                    continue;
+
+                if (token->identifier != NULL)
+                    push_long(token->identifier, num);
+
+                /* Set walk to the first non-number character */
+                walk = end;
+                next_state(token);
+                token_handled = true;
+                break;
+            }
+
             if (strcmp(token->name, "string") == 0 ||
                 strcmp(token->name, "word") == 0) {
                 char *str = parse_string(&walk, (token->name[0] != 's'));
index 2b4572b017fb32dc061cea9ae0f19088dcbe291f..0f3d33ec0600ca23b56e2e25a1d7e1dd34a6d804 100644 (file)
@@ -122,7 +122,7 @@ static void push_string(const char *identifier, const char *str) {
     /* When we arrive here, the stack is full. This should not happen and
      * means there’s either a bug in this parser or the specification
      * contains a command with more than 10 identified tokens. */
-    fprintf(stderr, "BUG: commands_parser stack full. This means either a bug "
+    fprintf(stderr, "BUG: config_parser stack full. This means either a bug "
                     "in the code, or a new command which contains more than "
                     "10 identified tokens.\n");
     exit(1);
@@ -142,7 +142,7 @@ static void push_long(const char *identifier, long num) {
     /* When we arrive here, the stack is full. This should not happen and
      * means there’s either a bug in this parser or the specification
      * contains a command with more than 10 identified tokens. */
-    fprintf(stderr, "BUG: commands_parser stack full. This means either a bug "
+    fprintf(stderr, "BUG: config_parser stack full. This means either a bug "
                     "in the code, or a new command which contains more than "
                     "10 identified tokens.\n");
     exit(1);
@@ -178,53 +178,6 @@ static void clear_stack(void) {
     }
 }
 
-// TODO: remove this if it turns out we don’t need it for testing.
-#if 0
-/*******************************************************************************
- * A dynamically growing linked list which holds the criteria for the current
- * command.
- ******************************************************************************/
-
-typedef struct criterion {
-    char *type;
-    char *value;
-
-    TAILQ_ENTRY(criterion) criteria;
-} criterion;
-
-static TAILQ_HEAD(criteria_head, criterion) criteria =
-  TAILQ_HEAD_INITIALIZER(criteria);
-
-/*
- * Stores the given type/value in the list of criteria.
- * Accepts a pointer as first argument, since it is 'call'ed by the parser.
- *
- */
-static void push_criterion(void *unused_criteria, const char *type,
-                           const char *value) {
-    struct criterion *criterion = smalloc(sizeof(struct criterion));
-    criterion->type = sstrdup(type);
-    criterion->value = sstrdup(value);
-    TAILQ_INSERT_TAIL(&criteria, criterion, criteria);
-}
-
-/*
- * Clears the criteria linked list.
- * Accepts a pointer as first argument, since it is 'call'ed by the parser.
- *
- */
-static void clear_criteria(void *unused_criteria) {
-    struct criterion *criterion;
-    while (!TAILQ_EMPTY(&criteria)) {
-        criterion = TAILQ_FIRST(&criteria);
-        free(criterion->type);
-        free(criterion->value);
-        TAILQ_REMOVE(&criteria, criterion, criteria);
-        free(criterion);
-    }
-}
-#endif
-
 /*******************************************************************************
  * The parser itself.
  ******************************************************************************/
index 400d319239ec6149df3c4d8046cd544c22faf9de..b7950c20b40ca18cc293654b0752f545bd759843 100644 (file)
@@ -261,7 +261,7 @@ void startup_monitor_event(SnMonitorEvent *event, void *userdata) {
  * Renames workspaces that are mentioned in the startup sequences.
  *
  */
-void startup_sequence_rename_workspace(char *old_name, char *new_name) {
+void startup_sequence_rename_workspace(const char *old_name, const char *new_name) {
     struct Startup_Sequence *current;
     TAILQ_FOREACH(current, &startup_sequences, sequences) {
         if (strcmp(current->workspace, old_name) != 0)
index d3a97453187ee63efefb66f92db78f8e8a722100..e7a09c70e3c32e5ebe12b53c964139420f2b5ab4 100644 (file)
@@ -918,7 +918,7 @@ Con *workspace_encapsulate(Con *ws) {
  * Move the given workspace to the specified output.
  * This returns true if and only if moving the workspace was successful.
  */
-bool workspace_move_to_output(Con *ws, char *name) {
+bool workspace_move_to_output(Con *ws, const char *name) {
     LOG("Trying to move workspace %p / %s to output \"%s\".\n", ws, ws->name, name);
 
     Con *current_output_con = con_get_output(ws);
index 4f555b29d4a42c3d5fe3824abdb51ec8bd0f368b..a56d668ea56bca6c8ba51b668196bc05da9eb2dd 100644 (file)
@@ -216,7 +216,7 @@ is(parser_calls('workspace "foo\\\\\\"bar"'),
 ################################################################################
 
 is(parser_calls("resize shrink width 10 px or"),
-   "ERROR: Expected one of these tokens: <word>\n" .
+   "ERROR: Expected one of these tokens: <number>\n" .
    "ERROR: Your command: resize shrink width 10 px or\n" .
    "ERROR:                                           ",
    "error for resize command with incomplete 'or'-construction ok");