Ignore:
Timestamp:
Dec 29, 2008, 11:20:11 PM (17 years ago)
Author:
bird
Message:

kmk: Implemented $(for ) and $(while ) loops (C-style). Fixes #73.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/function.c

    r2160 r2161  
    10711071}
    10721072
     1073#ifdef CONFIG_WITH_LOOP_FUNCTIONS
     1074
     1075
     1076/* Helper for func_for that evaluates the INIT and NEXT parts. */
     1077static void
     1078helper_eval (char *text, size_t text_len)
     1079{
     1080    unsigned int buf_len;
     1081    char *buf;
     1082
     1083    install_variable_buffer (&buf, &buf_len);
     1084    eval_buffer (text, text + text_len);
     1085    restore_variable_buffer (buf, buf_len);
     1086}
     1087
     1088/*
     1089  $(for init,condition,next,body)
     1090  */
     1091static char *
     1092func_for (char *o, char **argv, const char *funcname UNUSED)
     1093{
     1094  char        *init     = argv[0];
     1095  const char  *cond     = argv[1];
     1096  const char  *next     = argv[2];
     1097  size_t       next_len = strlen (next);
     1098  char        *next_buf = xmalloc (next_len + 1);
     1099  const char  *body     = argv[3];
     1100  size_t       body_len = strlen (body);
     1101  unsigned int doneany  = 0;
     1102
     1103  push_new_variable_scope ();
     1104
     1105  /* Evaluate INIT. */
     1106
     1107  helper_eval (init, strlen (init));
     1108
     1109  /* Loop till COND is false. */
     1110
     1111  while (expr_eval_if_conditionals (cond, NULL) == 0 /* true */)
     1112    {
     1113      /* Expand BODY. */
     1114
     1115      if (!doneany)
     1116        doneany = 1;
     1117      else
     1118        o = variable_buffer_output (o, " ", 1);
     1119      variable_expand_string_2 (o, body, body_len, &o);
     1120
     1121      /* Evaluate NEXT. */
     1122
     1123      memcpy (next_buf, next, next_len + 1);
     1124      helper_eval (next_buf, next_len);
     1125    }
     1126
     1127  pop_variable_scope ();
     1128  free (next_buf);
     1129
     1130  return o;
     1131}
     1132
     1133/*
     1134  $(while condition,body)
     1135 */
     1136static char *
     1137func_while (char *o, char **argv, const char *funcname UNUSED)
     1138{
     1139  const char  *cond     = argv[0];
     1140  const char  *body     = argv[1];
     1141  size_t       body_len = strlen (body);
     1142  unsigned int doneany  = 0;
     1143
     1144  push_new_variable_scope ();
     1145
     1146  while (expr_eval_if_conditionals (cond, NULL) == 0 /* true */)
     1147    {
     1148      if (!doneany)
     1149        doneany = 1;
     1150      else
     1151        o = variable_buffer_output (o, " ", 1);
     1152      variable_expand_string_2 (o, body, body_len, &o);
     1153    }
     1154
     1155  pop_variable_scope ();
     1156
     1157  return o;
     1158}
     1159
     1160
     1161#endif /* CONFIG_WITH_LOOP_FUNCTIONS */
     1162
    10731163struct a_word
    10741164{
     
    48664956  { STRING_SIZE_TUPLE("origin"),        0,  1,  1,  func_origin},
    48674957  { STRING_SIZE_TUPLE("foreach"),       3,  3,  0,  func_foreach},
     4958#ifdef CONFIG_WITH_LOOP_FUNCTIONS
     4959  { STRING_SIZE_TUPLE("for"),           4,  4,  0,  func_for},
     4960  { STRING_SIZE_TUPLE("while"),         2,  2,  0,  func_while},
     4961#endif
    48684962  { STRING_SIZE_TUPLE("call"),          1,  0,  1,  func_call},
    48694963  { STRING_SIZE_TUPLE("info"),          0,  1,  1,  func_error},
Note: See TracChangeset for help on using the changeset viewer.