PageRenderTime 63ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/src/parser.y

https://bitbucket.org/stephan_cr/stsh
Happy | 202 lines | 178 code | 24 blank | 0 comment | 0 complexity | 2a01c27fbb3cc39592f9b965818e630a MD5 | raw file
  1. /*
  2. * Copyright (C) 2005, 2011 Stephan Creutz
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  17. * 02111-1307, USA.
  18. *
  19. * The GNU General Public License is contained in the file COPYING.
  20. */
  21. %{
  22. #define YYSTYPE char *
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "parser.h"
  27. /* forward declarations to avoid compiler warnings */
  28. extern int yylex();
  29. static void init();
  30. static void cleanup();
  31. static void add_cmd(const char *name);
  32. static void add_param(const char *p);
  33. static void set_background();
  34. static void set_input_redirect(const char *filename);
  35. static void set_output_redirect(const char *filename);
  36. static void yyerror(const char *s);
  37. %}
  38. %token
  39. INPUT_REDIRECT
  40. OUTPUT_REDIRECT
  41. PIPE
  42. BACKGROUND
  43. PARAMETER
  44. FIRST_COMMAND_NAME
  45. COMMAND_NAME
  46. REST
  47. %start S
  48. %%
  49. S : { init(); } first_command { YYACCEPT; }
  50. | /**/
  51. | error { cleanup(); YYABORT; }
  52. ;
  53. first_command : command
  54. | command background
  55. | command input_redirect
  56. | command output_redirect
  57. | command input_redirect background
  58. | command output_redirect background
  59. | command input_redirect output_redirect
  60. | command input_redirect output_redirect background
  61. | command output_redirect input_redirect
  62. | command output_redirect input_redirect background
  63. | command pipe_command
  64. ;
  65. pipe_command : PIPE command
  66. | PIPE command background
  67. | PIPE command output_redirect
  68. | PIPE command output_redirect background
  69. | PIPE command pipe_command
  70. ;
  71. command : command_name
  72. | command_name parameter_list
  73. ;
  74. command_name : COMMAND_NAME { add_cmd($1); }
  75. ;
  76. parameter_list : PARAMETER { add_param($1); }
  77. | parameter_list PARAMETER { add_param($2); }
  78. ;
  79. input_redirect : INPUT_REDIRECT PARAMETER { set_input_redirect($2); }
  80. ;
  81. output_redirect : OUTPUT_REDIRECT PARAMETER { set_output_redirect($2); }
  82. ;
  83. background : BACKGROUND { set_background(); }
  84. ;
  85. %%
  86. static struct cmds *cmds_curr = NULL;
  87. static void init()
  88. {
  89. cmds_head = NULL;
  90. background = 0;
  91. cmds_curr = NULL;
  92. }
  93. static void cleanup()
  94. {
  95. struct cmds *p;
  96. int i;
  97. while (cmds_head != NULL) {
  98. p = cmds_head;
  99. if (p->name != NULL) free(p->name);
  100. for (i = 0; i < cmds_head->num_params; i++) {
  101. free(cmds_head->parameter_list[i]);
  102. }
  103. cmds_head = cmds_head->next;
  104. free(p);
  105. }
  106. init();
  107. }
  108. static void add_cmd(const char *name)
  109. {
  110. struct cmds *p, *mem;
  111. p = cmds_head;
  112. mem = malloc(sizeof(struct cmds));
  113. if (mem == NULL) {
  114. fprintf(stderr, "unable to allocate memory\n");
  115. exit(1);
  116. }
  117. memset(mem, 0, sizeof(struct cmds));
  118. if (p != NULL) {
  119. while (p->next != NULL) {
  120. p = p->next;
  121. }
  122. p->next = mem;
  123. p = p->next;
  124. } else {
  125. cmds_head = mem;
  126. p = cmds_head;
  127. }
  128. p->name = strdup(name);
  129. p->num_params = 0;
  130. p->input_file = NULL;
  131. p->output_file = NULL;
  132. p->next = NULL;
  133. cmds_curr = p;
  134. add_param(name);
  135. }
  136. static void add_param(const char *p)
  137. {
  138. if (cmds_curr->num_params == (MAX_PARAM - 1)) {
  139. fprintf(stderr, "too much parameters\n");
  140. exit(1);
  141. }
  142. cmds_curr->parameter_list[cmds_curr->num_params++] = strdup(p);
  143. }
  144. static void set_background()
  145. {
  146. background = 1;
  147. }
  148. static void set_input_redirect(const char *filename)
  149. {
  150. cmds_curr->input_file = strdup(filename);
  151. }
  152. static void set_output_redirect(const char *filename)
  153. {
  154. cmds_curr->output_file = strdup(filename);
  155. }
  156. static void yyerror(const char *s)
  157. {
  158. switch (yychar) {
  159. case INPUT_REDIRECT:
  160. fprintf(stderr, "invalid < in command\n");
  161. break;
  162. case OUTPUT_REDIRECT:
  163. fprintf(stderr, "invalid > in command\n");
  164. break;
  165. case PIPE:
  166. fprintf(stderr, "invalid | in command\n");
  167. break;
  168. case BACKGROUND:
  169. fprintf(stderr, "invalid & in command\n");
  170. break;
  171. case REST:
  172. fprintf(stderr, "character \"%s\" not allowed\n",
  173. yylval);
  174. break;
  175. default:
  176. fprintf(stderr, "%s: Invalid command\n", s);
  177. }
  178. }