X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Flabel.c;h=a7d1b768aae0b330906eb47b538cf87954c7206e;hb=4137d8ab47939bf6d83eb5153ec854c5da0f776d;hp=c62a4e69d7fbb67fe625f17b25719c3c2bb2bb1e;hpb=b9f3f7b83102ae1ef9a018d248cf91c42727433b;p=bacula%2Fbacula diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index c62a4e69d7..a7d1b768aa 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -8,7 +8,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2004 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -31,7 +31,7 @@ #include "stored.h" /* pull in Storage Deamon headers */ /* Forward referenced functions */ -static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec); +static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec); extern char my_name[]; extern int debug_level; @@ -56,19 +56,21 @@ extern int debug_level; * VOL_LABEL_ERROR * VOL_NO_MEDIA */ -int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +int read_dev_volume_label(DCR *dcr, DEV_BLOCK *block) { + JCR *jcr = dcr->jcr; + DEVICE *dev = dcr->dev; char *VolName = jcr->VolumeName; DEV_RECORD *record; - int ok = 0; + bool ok = false; Dmsg3(100, "Enter read_volume_label device=%s vol=%s dev_Vol=%s\n", dev_name(dev), VolName, dev->VolHdr.VolName); - if (dev->state & ST_LABEL) { /* did we already read label? */ + if (dev_state(dev, ST_LABEL)) { /* did we already read label? */ /* Compare Volume Names allow special wild card */ if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) { - Mmsg(&jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), + Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), dev_name(dev), VolName, dev->VolHdr.VolName); /* * Cancel Job if too many label errors @@ -86,7 +88,7 @@ int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ); /* set no label, no append */ if (!rewind_dev(dev)) { - Mmsg(&jcr->errmsg, _("Couldn't rewind device %s ERR=%s\n"), dev_name(dev), + Mmsg(jcr->errmsg, _("Couldn't rewind device %s ERR=%s\n"), dev_name(dev), strerror_dev(dev)); return jcr->label_status = VOL_NO_MEDIA; } @@ -95,22 +97,28 @@ int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Read the Volume label block */ record = new_record(); Dmsg0(90, "Big if statement in read_volume_label\n"); - if (!read_block_from_dev(jcr, dev, block, NO_BLOCK_NUMBER_CHECK)) { - Mmsg(&jcr->errmsg, _("Volume on %s is not a Bacula labeled Volume, \ -because:\n %s"), dev_name(dev), strerror_dev(dev)); + if (!read_block_from_dev(dcr, block, NO_BLOCK_NUMBER_CHECK)) { + Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula " + "labeled Volume, because: ERR=%s"), NPRT(VolName), dev_name(dev), + strerror_dev(dev)); } else if (!read_record_from_block(block, record)) { - Mmsg(&jcr->errmsg, _("Could not read Volume label from block.\n")); + Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n")); } else if (!unser_volume_label(dev, record)) { - Mmsg(&jcr->errmsg, _("Could not unserialize Volume label: %s\n"), + Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"), strerror_dev(dev)); } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 && strcmp(dev->VolHdr.Id, OldBaculaId) != 0) { - Mmsg(&jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id); + Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id); } else { - ok = 1; + ok = true; } if (!ok) { free_record(record); + if (forge_on || jcr->ignore_label_errors) { + dev->state |= ST_LABEL; /* set has Bacula label */ + Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg); + return jcr->label_status = VOL_OK; + } empty_block(block); rewind_dev(dev); return jcr->label_status = VOL_NO_LABEL; @@ -126,15 +134,26 @@ because:\n %s"), dev_name(dev), strerror_dev(dev)); if (dev->VolHdr.VerNum != BaculaTapeVersion && dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion1 && dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) { - Mmsg(&jcr->errmsg, _("Volume on %s has wrong Bacula version. Wanted %d got %d\n"), + Mmsg(jcr->errmsg, _("Volume on %s has wrong Bacula version. Wanted %d got %d\n"), dev_name(dev), BaculaTapeVersion, dev->VolHdr.VerNum); return jcr->label_status = VOL_VERSION_ERROR; } + /* We are looking for either an unused Bacula tape (PRE_LABEL) or + * a Bacula volume label (VOL_LABEL) + */ + if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) { + Mmsg(jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"), + dev_name(dev), dev->VolHdr.LabelType); + return jcr->label_status = VOL_LABEL_ERROR; + } + + dev->state |= ST_LABEL; /* set has Bacula label */ + /* Compare Volume Names */ Dmsg2(30, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolName); if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) { - Mmsg(&jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), + Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), dev_name(dev), VolName, dev->VolHdr.VolName); /* * Cancel Job if too many label errors @@ -147,16 +166,6 @@ because:\n %s"), dev_name(dev), strerror_dev(dev)); } Dmsg1(30, "Copy vol_name=%s\n", dev->VolHdr.VolName); - /* We are looking for either an unused Bacula tape (PRE_LABEL) or - * a Bacula volume label (VOL_LABEL) - */ - if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) { - Mmsg(&jcr->errmsg, _("Volume on %s has bad Bacula label type: %x\n"), - dev_name(dev), dev->VolHdr.LabelType); - return jcr->label_status = VOL_LABEL_ERROR; - } - - dev->state |= ST_LABEL; /* set has Bacula label */ if (debug_level >= 10) { dump_volume_label(dev); } @@ -171,20 +180,22 @@ because:\n %s"), dev_name(dev), strerror_dev(dev)); * * Assumes that the record is already read. * - * Returns: 0 on error - * 1 on success + * Returns: false on error + * true on success */ -int unser_volume_label(DEVICE *dev, DEV_RECORD *rec) +bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec) { ser_declare; if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) { - Mmsg3(&dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"), + Mmsg3(dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"), FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); - return 0; + if (!forge_on) { + return false; + } } dev->VolHdr.LabelType = rec->FileIndex; @@ -223,24 +234,26 @@ int unser_volume_label(DEVICE *dev, DEV_RECORD *rec) if (debug_level >= 90) { dump_volume_label(dev); } - return 1; + return true; } /* * Put a volume label into the block * - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) +bool write_volume_label_to_block(DCR *dcr, DEV_BLOCK *block) { DEV_RECORD rec; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; Dmsg0(20, "write Label in write_volume_label_to_block()\n"); memset(&rec, 0, sizeof(rec)); rec.data = get_memory(SER_LENGTH_Volume_Label); - create_volume_label_record(jcr, dev, &rec); + create_volume_label_record(dcr, &rec); empty_block(block); /* Volume label always at beginning */ block->BlockNumber = 0; @@ -248,12 +261,12 @@ int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) free_pool_memory(rec.data); Jmsg1(jcr, M_FATAL, 0, _("Cannot write Volume label to block for device %s\n"), dev_name(dev)); - return 0; + return false; } else { Dmsg1(90, "Wrote label of %d bytes to block\n", rec.data_len); } free_pool_memory(rec.data); - return 1; + return true; } /* @@ -262,10 +275,12 @@ int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * Assumes that the dev->VolHdr structure is properly * initialized. */ -static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec) +static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec) { ser_declare; struct date_time dt; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; /* Serialize the label into the device record. */ @@ -316,12 +331,9 @@ static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec) /* * Create a volume label in memory - * Returns: 0 on error - * 1 on success */ -void create_volume_label(DEVICE *dev, char *VolName, char *PoolName) +void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName) { - struct date_time dt; DEVRES *device = (DEVRES *)dev->device; Dmsg0(90, "Start create_volume_label()\n"); @@ -330,9 +342,6 @@ void create_volume_label(DEVICE *dev, char *VolName, char *PoolName) memset(&dev->VolHdr, 0, sizeof(dev->VolHdr)); - /* ***FIXME*** we really need to get the volume name, - * pool name, and pool type from the database. - */ bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id)); dev->VolHdr.VerNum = BaculaTapeVersion; dev->VolHdr.LabelType = PRE_LABEL; /* Mark tape as unused */ @@ -342,17 +351,9 @@ void create_volume_label(DEVICE *dev, char *VolName, char *PoolName) bstrncpy(dev->VolHdr.PoolType, "Backup", sizeof(dev->VolHdr.PoolType)); - /* Put label time/date in header */ - if (BaculaTapeVersion >= 11) { - dev->VolHdr.label_btime = get_current_btime(); - dev->VolHdr.label_date = 0; - dev->VolHdr.label_time = 0; - } else { - /* OLD WAY DEPRECATED */ - get_current_time(&dt); - dev->VolHdr.label_date = dt.julian_day_number; - dev->VolHdr.label_time = dt.julian_day_fraction; - } + dev->VolHdr.label_btime = get_current_btime(); + dev->VolHdr.label_date = 0; + dev->VolHdr.label_time = 0; if (gethostname(dev->VolHdr.HostName, sizeof(dev->VolHdr.HostName)) != 0) { dev->VolHdr.HostName[0] = 0; @@ -377,12 +378,12 @@ void create_volume_label(DEVICE *dev, char *VolName, char *PoolName) * * This routine should be used only when labeling a blank tape. */ -int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName) +bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName) { - DEVICE *dev = device->dev; DEV_RECORD rec; DEV_BLOCK *block; - int stat = 1; + bool ok = false; + DEVICE *dev = dcr->dev; Dmsg0(99, "write_volume_label()\n"); @@ -391,43 +392,45 @@ int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *Poo if (!rewind_dev(dev)) { memset(&dev->VolHdr, 0, sizeof(dev->VolHdr)); Dmsg2(30, "Bad status on %s from rewind. ERR=%s\n", dev_name(dev), strerror_dev(dev)); - return 0; + if (!forge_on) { + return false; + } } block = new_block(dev); memset(&rec, 0, sizeof(rec)); rec.data = get_memory(SER_LENGTH_Volume_Label); - create_volume_label_record(jcr, dev, &rec); + create_volume_label_record(dcr, &rec); rec.Stream = 0; if (!write_record_to_block(block, &rec)) { Dmsg2(30, "Bad Label write on %s. ERR=%s\n", dev_name(dev), strerror_dev(dev)); memset(&dev->VolHdr, 0, sizeof(dev->VolHdr)); - free_block(block); - free_pool_memory(rec.data); - return 0; + goto bail_out; } else { Dmsg2(30, "Wrote label of %d bytes to %s\n", rec.data_len, dev_name(dev)); } - free_pool_memory(rec.data); - Dmsg0(99, "Call write_block_to_device()\n"); - if (!write_block_to_dev(jcr, dev, block)) { + Dmsg0(99, "Call write_block_to_dev()\n"); + if (!write_block_to_dev(dcr, block)) { memset(&dev->VolHdr, 0, sizeof(dev->VolHdr)); Dmsg2(30, "Bad Label write on %s. ERR=%s\n", dev_name(dev), strerror_dev(dev)); - stat = 9; + goto bail_out; } Dmsg0(99, " Wrote block to device\n"); - flush_dev(dev); weof_dev(dev, 1); dev->state |= ST_LABEL; + ok = true; if (debug_level >= 20) { dump_volume_label(dev); } + +bail_out: free_block(block); - return stat; + free_pool_memory(rec.data); + return ok; } @@ -435,8 +438,9 @@ int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *Poo * Create session label * The pool memory must be released by the calling program */ -void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) +void create_session_label(DCR *dcr, DEV_RECORD *rec, int label) { + JCR *jcr = dcr->jcr; ser_declare; rec->VolSessionId = jcr->VolSessionId; @@ -470,10 +474,10 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) if (label == EOS_LABEL) { ser_uint32(jcr->JobFiles); ser_uint64(jcr->JobBytes); - ser_uint32(jcr->StartBlock); - ser_uint32(jcr->EndBlock); - ser_uint32(jcr->StartFile); - ser_uint32(jcr->EndFile); + ser_uint32(dcr->StartBlock); + ser_uint32(dcr->EndBlock); + ser_uint32(dcr->StartFile); + ser_uint32(dcr->EndFile); ser_uint32(jcr->JobErrors); /* Added in VerNum 11 */ @@ -484,12 +488,13 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) } /* Write session label - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) +bool write_session_label(DCR *dcr, DEV_BLOCK *block, int label) { - DEVICE *dev = jcr->device->dev; + JCR *jcr = dcr->jcr; + DEVICE *dev = dcr->dev; DEV_RECORD *rec; rec = new_record(); @@ -497,27 +502,27 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) switch (label) { case SOS_LABEL: if (dev->state & ST_TAPE) { - jcr->StartBlock = dev->block_num; - jcr->StartFile = dev->file; + dcr->StartBlock = dev->block_num; + dcr->StartFile = dev->file; } else { - jcr->StartBlock = (uint32_t)dev->file_addr; - jcr->StartFile = (uint32_t)(dev->file_addr >> 32); + dcr->StartBlock = (uint32_t)dev->file_addr; + dcr->StartFile = (uint32_t)(dev->file_addr >> 32); } break; case EOS_LABEL: if (dev->state & ST_TAPE) { - jcr->EndBlock = dev->EndBlock; - jcr->EndFile = dev->EndFile; + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; } else { - jcr->EndBlock = (uint32_t)dev->file_addr; - jcr->EndFile = (uint32_t)(dev->file_addr >> 32); + dcr->EndBlock = (uint32_t)dev->file_addr; + dcr->EndFile = (uint32_t)(dev->file_addr >> 32); } break; default: Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label); break; } - create_session_label(jcr, rec, label); + create_session_label(dcr, rec, label); rec->FileIndex = label; /* @@ -529,19 +534,19 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) */ if (!can_write_record_to_block(block, rec)) { Dmsg0(100, "Cannot write session label to block.\n"); - if (!write_block_to_device(jcr, dev, block)) { + if (!write_block_to_device(jcr->dcr, block)) { Dmsg0(90, "Got session label write_block_to_dev error.\n"); Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"), dev_vol_name(dev), strerror(errno)); free_record(rec); - return 0; + return false; } } if (!write_record_to_block(block, rec)) { Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"), dev_vol_name(dev), strerror(errno)); free_record(rec); - return 0; + return false; } Dmsg6(20, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n\ @@ -553,14 +558,15 @@ remainder=%d\n", jcr->JobId, free_record(rec); Dmsg2(20, "Leave write_session_label Block=%d File=%d\n", dev->block_num, dev->file); - return 1; + return true; } void dump_volume_label(DEVICE *dev) { int dbl = debug_level; uint32_t File; - char *LabelType, buf[30]; + const char *LabelType; + char buf[30]; struct tm tm; struct date_time dt; @@ -627,7 +633,7 @@ bail_out: debug_level = dbl; } -int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec) +bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec) { ser_declare; @@ -671,11 +677,11 @@ int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec) label->JobStatus = JS_Terminated; /* kludge */ } } - return 1; + return true; } -static void dump_session_label(DEV_RECORD *rec, char *type) +static void dump_session_label(DEV_RECORD *rec, const char *type) { int dbl; struct date_time dt; @@ -744,79 +750,88 @@ Date written : %04d-%02d-%02d at %02d:%02d\n"), void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose) { - char *type; + const char *type; int dbl; dbl = debug_level; debug_level = 1; switch (rec->FileIndex) { + case PRE_LABEL: + type = _("Fresh Volume"); + break; + case VOL_LABEL: + type = _("Volume"); + break; + case SOS_LABEL: + type = _("Begin Job Session"); + break; + case EOS_LABEL: + type = _("End Job Session"); + break; + case EOM_LABEL: + type = _("End of Media"); + break; + case EOT_LABEL: + type = ("End of Tape"); + break; + default: + type = _("Unknown"); + break; + } + if (verbose) { + switch (rec->FileIndex) { case PRE_LABEL: - type = _("Fresh Volume"); - break; case VOL_LABEL: - type = _("Volume"); + unser_volume_label(dev, rec); + dump_volume_label(dev); break; case SOS_LABEL: - type = _("Begin Session"); + dump_session_label(rec, type); break; case EOS_LABEL: - type = _("End Session"); + dump_session_label(rec, type); break; case EOM_LABEL: - type = _("End of Media"); + Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n", + type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); break; case EOT_LABEL: - type = ("End of Tape"); + Pmsg0(-1, _("End of physical tape.\n")); break; default: - type = _("Unknown"); + Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n", + type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); break; - } - if (verbose) { - switch (rec->FileIndex) { - case PRE_LABEL: - case VOL_LABEL: - unser_volume_label(dev, rec); - dump_volume_label(dev); - break; - case SOS_LABEL: - dump_session_label(rec, type); - break; - case EOS_LABEL: - dump_session_label(rec, type); - break; - case EOM_LABEL: - Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n", - type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - break; - case EOT_LABEL: - Pmsg0(-1, _("End of physical tape.\n")); - break; - default: - Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n", - type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - break; } } else { + SESSION_LABEL label; switch (rec->FileIndex) { - case SOS_LABEL: - case EOS_LABEL: - SESSION_LABEL label; - unser_session_label(&label, rec); - Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c \ -Type=%c\n", - type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, - label.JobLevel, label.JobType); - break; - case EOM_LABEL: - case PRE_LABEL: - case VOL_LABEL: - default: - Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n", - type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - break; - case EOT_LABEL: - break; + case SOS_LABEL: + unser_session_label(&label, rec); + Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c Type=%c\n", + type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, + label.JobLevel, label.JobType); + break; + case EOS_LABEL: + char ed1[30], ed2[30]; + unser_session_label(&label, rec); + Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c Type=%c\n", + type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, + label.JobLevel, label.JobType); + Pmsg4(-1, " Files=%s Bytes=%s Errors=%d Status=%c\n", + edit_uint64_with_commas(label.JobFiles, ed1), + edit_uint64_with_commas(label.JobBytes, ed2), + label.JobErrors, (char)label.JobStatus); + break; + case EOM_LABEL: + case PRE_LABEL: + case VOL_LABEL: + default: + Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n", + type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); + break; + case EOT_LABEL: + break; } } debug_level = dbl;