Index: main/features.c
===================================================================
--- main/features.c	(revision 200476)
+++ main/features.c	(working copy)
@@ -148,6 +148,14 @@
 			<para>If you set the <variable>PARKINGEXTEN</variable> variable to an extension in your
 			parking context, Park() will park the call on that extension, unless
 			it already exists. In that case, execution will continue at next priority.</para>
+			<para>Variable <variable>PARKINGLOT</variable> used for defining which parking lot will
+			be used</para>
+			<para>If you set <variable>PARKINGDYNAMIC</variable> parkinglot from features.conf with
+			that name will be used as base for dynamically created lot.</para>
+			<para>Variable <variable>PARKINGDYNCONTEXT</variable> define context for dynamically
+			created parking lot.</para>
+			<para>Variable <variable>PARKINGDYNPOS</variable> define parking positions to use in
+			dynamically created lot.</para>
 		</description>
 		<see-also>
 			<ref type="application">ParkAndAnnounce</ref>
@@ -291,6 +299,7 @@
 
 static char courtesytone[256];                             /*!< Courtesy tone */
 static int parkedplay = 0;                                 /*!< Who to play the courtesy tone to */
+static int parkeddynamic = 0;                              /*!< Enable creation of parkinglots dynamicaly */
 static char xfersound[256];                                /*!< Call transfer sound */
 static char xferfailsound[256];                            /*!< Call transfer failure sound */
 static char pickupsound[256];                              /*!< Pickup sound */
@@ -361,8 +370,9 @@
 static void parkinglot_destroy(void *obj);
 int manage_parkinglot(struct ast_parkinglot *curlot, fd_set *rfds, fd_set *efds, fd_set *nrfds, fd_set *nefds, int *fs, int *max);
 struct ast_parkinglot *find_parkinglot(const char *name);
+static struct ast_parkinglot *create_parkinglot(const char *name);
+static struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *);
 
-
 const char *ast_parking_ext(void)
 {
 	return parking_ext;
@@ -614,23 +624,59 @@
 	struct parkeduser *pu;
 };
 
-static struct parkeduser *park_space_reserve(struct ast_channel *chan,
- struct ast_channel *peer, struct ast_park_call_args *args)
+static struct parkeduser *park_space_reserve(struct ast_channel *chan, struct ast_channel *peer, struct ast_park_call_args *args)
 {
 	struct parkeduser *pu;
 	int i, parking_space = -1, parking_range;
 	const char *parkinglotname = NULL;
 	const char *parkingexten;
 	struct ast_parkinglot *parkinglot = NULL;
-	
+
 	if (peer)
 		parkinglotname = findparkinglotname(peer);
 
 	if (parkinglotname) {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Found chanvar Parkinglot: %s\n", parkinglotname);
-		parkinglot = find_parkinglot(parkinglotname);	
+		ast_debug(1, "Found chanvar Parkinglot: %s\n", parkinglotname);
+		parkinglot = find_parkinglot(parkinglotname);
 	}
+
+	if (!parkinglot && parkeddynamic && !ast_strlen_zero(parkinglotname)) { /* Dynamically create parkinglot */
+		const char *dyn_context, *dyn_range;
+		const char *parkinglotname_copy = NULL;
+		struct ast_parkinglot *parkinglot_copy = NULL;
+		int dyn_start, dyn_end;
+
+		ast_channel_lock(chan);
+		parkinglotname_copy = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNAMIC"),""));
+		dyn_context = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNCONTEXT"),""));
+		dyn_range = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGDYNPOS"),""));
+		ast_channel_unlock(chan);
+
+		if (!ast_strlen_zero(parkinglotname_copy)) {
+			parkinglot_copy = find_parkinglot(parkinglotname_copy);
+		}
+		if (!parkinglot_copy) {
+			parkinglot_copy = default_parkinglot;
+			ast_debug(1, "Using default parking lot for copy\n");
+		}
+		if(!(parkinglot = copy_parkinglot(parkinglotname, parkinglot_copy))) {
+			ast_log(LOG_ERROR, "Could not build dynamic parking lot!\n");
+		} else {
+			if (!ast_strlen_zero(dyn_context)) {
+				ast_copy_string(parkinglot->parking_con, dyn_context, sizeof(parkinglot->parking_con));
+			}
+			if (!ast_strlen_zero(dyn_range)) {
+				if (sscanf(dyn_range, "%d-%d", &dyn_start, &dyn_end) != 2) {
+					ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers\n");
+				} else {
+					parkinglot->parking_start = dyn_start;
+					parkinglot->parking_stop = dyn_end;
+				}
+			}
+			ao2_link(parkinglots, parkinglot);
+		}
+	}
+
 	if (!parkinglot)
 		parkinglot = default_parkinglot;
 
@@ -647,7 +693,9 @@
 	/* Lock parking list */
 	AST_LIST_LOCK(&parkinglot->parkings);
 	/* Check for channel variable PARKINGEXTEN */
-	parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
+	ast_channel_lock(chan);
+	parkingexten = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"),""));
+	ast_channel_unlock(chan);
 	if (!ast_strlen_zero(parkingexten)) {
 		/*!\note The API forces us to specify a numeric parking slot, even
 		 * though the architecture would tend to support non-numeric extensions
@@ -3350,6 +3398,26 @@
 	return parkinglot;
 }
 
+/*! \brief Copy parkinglot and store it with new name */
+struct ast_parkinglot *copy_parkinglot(const char *name, const struct ast_parkinglot *parkinglot) {
+	struct ast_parkinglot *copylot;
+
+	if (ast_strlen_zero(name)) { /* No name specified */
+		return NULL;
+	}
+	if (find_parkinglot(name)) { /* Parkinglot with that name allready exists */
+		return NULL;
+	}
+
+	copylot = create_parkinglot(name);
+	ast_debug(1, "Building parking lot %s\n", name);
+
+	memcpy(copylot, parkinglot, sizeof(struct ast_parkinglot));
+	ast_copy_string(copylot->name, name, sizeof(copylot->name));
+
+	return copylot;
+}
+
 AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS
 	AST_APP_OPTION('r', AST_PARK_OPT_RINGING),
 	AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE),
@@ -3629,7 +3697,7 @@
 }
 
 /*! \brief Allocate parking lot structure */
-static struct ast_parkinglot *create_parkinglot(char *name)
+static struct ast_parkinglot *create_parkinglot(const char *name)
 {
 	struct ast_parkinglot *newlot = (struct ast_parkinglot *) NULL;
 
@@ -3678,9 +3746,8 @@
 
 	ao2_lock(parkinglot);
 
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Building parking lot %s\n", name);
-	
+	ast_debug(1, "Building parking lot %s\n", name);
+
 	/* Do some config stuff */
 	while(confvar) {
 		if (!strcasecmp(confvar->name, "context")) {
@@ -3902,6 +3969,8 @@
 				default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
 			else if (!strcasecmp(var->value, "callee"))
 				default_parkinglot->parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
+		} else if (!strcasecmp(var->name, "parkeddynamic")) {
+			parkeddynamic = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "adsipark")) {
 			adsipark = ast_true(var->value);
 		} else if (!strcasecmp(var->name, "transferdigittimeout")) {
Index: configs/features.conf.sample
===================================================================
--- configs/features.conf.sample	(revision 200476)
+++ configs/features.conf.sample	(working copy)
@@ -27,6 +27,7 @@
                                 ; one of: callee, caller, both, no (default is no)
 ;parkedcallrecording = caller   ; Enables or disables DTMF based one-touch recording when picking up a parked call.
                                 ; one of: callee, caller, both, no (default is no)
+;parkeddynamic = no				; Enables of dynamic creation parked calls context (parkedcall section name if yes)
 ;adsipark = yes			; if you want ADSI parking announcements
 ;findslot => next		; Continue to the 'next' free parking space.
 				; Defaults to 'first' available
